← All articles
  1. Problem Statement and Scope
  2. Task Representation
  3. Priority Dimensions
  4. The Aggregate Scoring Function
  5. Temporal Urgency Amplification
  6. Queueing Model Integration
  7. Anti-Starvation via Aging
  8. Priority Class Assignment
  9. System Stability and Throughput
  10. Implementation Architecture

Operational platforms in universal banks process thousands of heterogeneous tasks daily—payment renegotiations, expiring mandates, SEPA return windows, nostro break escalations, regulatory deadline filings. A naive FIFO queue treats a low-stakes internal memo and a €50M same-day payment renegotiation identically. This paper formalises a multi-dimensional priority model that scores tasks across five orthogonal dimensions, integrates with a non-preemptive M/G/c priority queue, and provably prevents starvation through a time-dependent aging mechanism.

1. Problem Statement and Scope

Consider a banking operations platform that receives a stream of work items from multiple source systems: core banking, payment gateways, CRM, regulatory reporting, treasury, and custody. Each item demands human or automated processing within a defined time constraint. The platform must decide, at each scheduling cycle, which item to assign to the next available processor.

This decision is non-trivial because tasks differ across several incommensurable dimensions simultaneously. A payment renegotiation for a corporate client may carry a large financial exposure with a hard 17:00 CET intraday deadline. A SEPA mandate expiry may carry a smaller exposure but triggers a regulatory breach if not actioned before the Bulk Settlement cut-off. A fraud dispute may have no immediate financial impact but carries a reputational dimension and a regulatory 10-business-day SLA under PSD2. No single scalar captures all these considerations.

We define the Multi-Dimensional Priority Queue (MDPQ) as a scheduling policy that assigns to each task, at each point in time, a scalar priority score derived from a formal model of its characteristics, then executes a non-preemptive priority queue over that score.

2. Task Representation

A task is a tuple 𝒯 = ⟨ id, τa, τd, 𝒙, 𝒔 ⟩ where:

id is a unique identifier; τa ∈ ℝ≥0 is the arrival timestamp; τd ∈ ℝ≥0 ∪ {∞} is the hard deadline (∞ for tasks without one); 𝒙 ∈ ℝd is the feature vector; and 𝒔 ∈ 𝒮 is the task type (enum).

The feature vector 𝒙 encodes all task characteristics required by the scoring model. For a banking operations context, we define d = 10 base features, expanded to 5 scoring dimensions through dimension-specific transformations:

FeatureSymbolDomainDescription
x1A≥0Financial exposure amount (base currency)
x2τd − τRemaining time to hard deadline at evaluation time τ
x3r ∈ {1…5}Regulatory obligation level (5 = breach triggers supervisory action)
x4c ∈ {1…5}Counterparty tier (1 = systemically important, 5 = retail)
x5Rv[0,1]Revenue at risk as fraction of annual relationship value
x6s ∈ 𝒮enumTask type (renegotiation, mandate, dispute, return, break…)
x7Δτ = τ − τa≥0Age of task since arrival
x8ndep0Number of downstream tasks blocked by this one
x9ε ∈ {0,1}𝔹Escalation flag (set by business rule engine)
x10μ̂s>0Expected service time for task type s (hours)

3. Priority Dimensions

We define five orthogonal priority dimensions. Each dimension produces a normalised score in [0, 1] through a dimension-specific transformation fi : ℝd → [0,1].

Dimension 1 — Financial Exposure (𝒟fin)

Raw financial exposure exhibits heavy-tailed distribution (a few very large items, many small ones). A linear scaling would allow single large items to dominate. We apply a log-normalisation with soft truncation at a configurable ceiling Amax:

Eq. (1) — Financial Dimension Score 𝒟fin
f1(A) = ln(1 + A / A0)ln(1 + Amax / A0)
where A0 is the minimum meaningful exposure (e.g., €1,000), Amax is the 99th-percentile exposure ceiling used for normalisation. Exposures above Amax produce scores above 1; these are clipped to 1 and separately trigger an escalation flag ε = 1.

Dimension 2 — Temporal Urgency (𝒟time)

This is the most analytically interesting dimension. The urgency of a task should be low when the deadline is far away and rise sharply as it approaches. We use a hyperbolic urgency function with shape parameter α that controls how steeply urgency rises near the deadline:

Eq. (2) — Hyperbolic Urgency Function 𝒟time
f2(τ; τd, α, β) = 1 − exp(−α · βmax(τd − τ, ε)),     τ < τd
Parameters: α controls curvature (α = 1 gives near-linear growth; α > 2 concentrates urgency near the deadline); β is the urgency horizon in the same time units as τ (e.g., β = 4h means urgency is half its maximum when 4 hours remain); ε > 0 is a small floor to prevent division by zero. For τ ≥ τd (overdue), f2 = 1 and an escalation flag is set. For tasks without a hard deadline (τd = ∞), a soft deadline derived from task type SLA is substituted.
Urgency Function Family — f₂(Δt; α, β=4h)
Parametric curves of the hyperbolic urgency function for varying shape parameter α, with horizon β = 4 hours. x-axis: hours remaining until deadline. All curves are derived from Eq. (2) — no empirical data.
f₂(τ; τd, α, β) = 1 − exp(−α · β / max(τd − τ, ε))

Dimension 3 — Regulatory Obligation (𝒟reg)

Regulatory dimensions are inherently ordinal. We map the regulatory obligation level r ∈ {1,…,5} through a convex mapping that penalises the top levels disproportionately:

Eq. (3) — Regulatory Dimension Score 𝒟reg
f3(r) = eγ(r−1) − 1eγ(Rmax−1) − 1,     r ∈ {1, …, Rmax}
The parameter γ > 0 controls convexity. γ → 0 recovers a linear scale; γ = 1.5 gives approximately 2× weight to level 5 vs level 4. This models the non-linear cost of regulatory breach: a level-5 obligation (e.g., T+1 EMIR trade reporting) is not merely slightly worse than level 4—it triggers supervisory notification and potential capital add-on.

Dimension 4 — Counterparty Weight (𝒟cpty)

Counterparty importance enters the model as a concave decreasing function of tier (tier 1 = highest importance):

Eq. (4) — Counterparty Dimension Score 𝒟cpty
f4(c) = ln(Rmax − c + 2)ln(Rmax + 1)
This ensures a tier-1 counterparty scores f4 = 1 and the lowest tier approaches but does not reach 0. The concave shape reflects diminishing differentiation between lower tiers—operationally, the distinction between a tier-3 and tier-4 client matters less than the distinction between tier-1 and tier-2.

Dimension 5 — Dependency Weight (𝒟dep)

Tasks that block other tasks propagate their delay cost multiplicatively. A task blocking ndep downstream items has a dependency score:

Eq. (5) — Dependency Dimension Score 𝒟dep
f5(ndep) = 1 − 11 + ndep / η
The half-saturation parameter η sets the number of blocked dependents at which the score is 0.5. This uses a hyperbolic saturation (Michaelis-Menten form) to prevent runaway scores for tasks with many soft dependents.

4. The Aggregate Scoring Function

The aggregate priority score at evaluation time τ is a weighted sum of dimension scores modulated by a time-dependent amplification operator:

Eq. (6) — Aggregate Priority Score Core Model
P(𝒯, τ) = Ω(τd−τ) · [ Σi=15 wi · fi(𝒙, τ) ] + ℬ(τ−τa) + κ · ε
Ω(Δt) — the deadline amplification operator (§5); wi — dimension weights with Σwi = 1; ℬ(Δτ) — the aging bonus as a function of task age (§7); ε — escalation binary flag; κ — escalation weight (typically 0.2–0.4, added directly to the score). The score is not strictly bounded to [0,1] when aging and escalation bonuses apply; this is intentional, as it guarantees overdue and escalated tasks cannot be outranked by newly arrived tasks.

Weight calibration is the most consequential design decision. The weights w = (w1,…,w5) must be elicited from business stakeholders and validated against historical outcomes. A reference configuration for a payment operations platform:

DimensionSymbolReference Weight wiRationale
Financial Exposurew10.30Dominant driver; direct P&L impact
Temporal Urgencyw20.28Hard deadlines are non-negotiable; close second
Regulatory Obligationw30.22Breach has asymmetric cost; overweighted relative to frequency
Counterparty Weightw40.12Relationship management; lower weight than operational urgency
Dependencyw50.08Indirect cost; important for long chains but rare
Score Sensitivity to Weight Perturbation — Radar Analysis
Normalised partial derivative ∂P/∂wi evaluated at the reference weight configuration for three canonical task archetypes. Shows which dimensions are most controlling for each task type. Model-derived, no empirical data.

"The weights are not a free parameter—they are a policy statement. Choosing w3 = 0.22 is an assertion that regulatory breach is roughly 73% as important as financial exposure, and must be defensible to the risk committee."

5. Temporal Urgency Amplification

The deadline amplification operator Ω(Δt) is a global multiplier applied to the weighted sum, distinct from the per-task urgency dimension f2. It encodes the intuition that as any task approaches its deadline, the entire priority vector should be boosted—not just the temporal component:

Eq. (7) — Deadline Amplification Operator Ω
Ω(Δt) = 1 + ω · exp(−δ · Δt),     Δt = τd − τ ≥ 0
ω ≥ 0 — maximum amplification above 1.0 (e.g., ω = 0.5 allows up to 50% boost at Δt → 0); δ > 0 — decay rate (1/δ is the characteristic amplification horizon in hours). For tasks with no deadline (τd = ∞), Ω = 1. For overdue tasks, Ω = 1 + ω (maximum), as Δt is set to 0 in the formula. This two-parameter family separates the magnitude of urgency amplification (ω) from the timing at which it activates (δ).
Eq. (8) — Expanded Priority Score
P(𝒯, τ) = (1 + ω · e−δ(τd−τ)) · Σi wi fi + Amax(1 − e−μ(τ−τa)) + κε
This is the fully expanded form of the MDPQ scoring function. The three additive components have clear semantic separation: (1) time-amplified weighted multi-criteria score, (2) anti-starvation aging bonus, (3) escalation override.

6. Queueing Model Integration

The MDPQ scoring function assigns tasks to priority classes (§8), which then enter a non-preemptive M/G/c priority queue. We adopt the following model: task arrivals follow a Poisson process with class-specific rates λk; service times follow a general distribution with mean μ̄k−1 and second moment E[Sk2]; there are c homogeneous parallel processors.

Utilisation

Eq. (9) — Per-Class and Total Utilisation
ρk = λkc · μk,      ρ = Σk=1K ρk < 1
Stability requires total utilisation ρ < 1. With K priority classes, each must contribute ρk such that their sum is sub-critical.

Expected Waiting Time — Non-Preemptive Priority

For a non-preemptive priority queue (higher-priority tasks cannot interrupt a task already in service), the expected waiting time for class k follows the Pollaczek–Khinchine priority formula:

Eq. (10) — Expected Wait Time, Class k (Non-Preemptive P-K) Core
Wk = W0(1 − σk−1)(1 − σk)
where σk = Σj=1k ρj is the cumulative utilisation through class k, σ0 = 0, and W0 is the mean residual service time at an arbitrary arrival epoch:
Eq. (11) — Mean Residual Service Time
W0 = 12 Σk=1K λk · E[Sk2]
For exponential service times, E[Sk2] = 2/μk2, which gives W0 = Σk ρkk. High coefficient-of-variation service time distributions (common in banking operations, where a renegotiation may take 2 minutes or 2 hours) inflate W0 and increase waiting time for all classes — a strong incentive for task typing and routing optimisation.
Expected Wait Time vs System Utilisation — 3-Class Priority Queue
Normalised expected wait time Wk/W0 for three priority classes as a function of total utilisation ρ. Derived from Eq. (10) with equal class utilisation (ρk = ρ/3). Non-preemptive discipline. As ρ → 1, class-3 wait time diverges while class-1 remains bounded.
Wk = W0 / [(1 − σk−1)(1 − σk)] where σk = Σj≤k ρj

SLA Breach Probability

The probability that a class-k task misses its SLA deadline τSLA can be approximated, under exponential service and Poisson arrivals, from the waiting time distribution. For M/M/1 sub-queues (one-class isolation), the complementary CDF of waiting time is:

Eq. (12) — SLA Breach Probability (M/M/1 Approximation)
P(Wk > τSLA) ≈ ρkeff · exp(−μk(1−ρkeff) · τSLA)
where ρkeff = σk − σk−1 is the effective load seen by class k under the priority discipline. This approximation is conservative for lower priority classes (overestimates breach probability) and can be used to set dynamic escalation thresholds: if P(Wk > τSLA) exceeds a configured tolerance θ, the task is promoted one priority class.
SLA Breach Probability vs Remaining SLA Window — By Priority Class
P(breach) curves from Eq. (12) for three priority classes at ρ = 0.75, μ = 2 tasks/hour. x-axis: remaining time in SLA window. Breach probability feeds back into the urgency dimension (§3.2) and triggers class promotion when it exceeds threshold θ.
P(Wk > t) ≈ ρkeff · exp(−μk(1−ρkeff) · t)

7. Anti-Starvation via Aging

A pure priority queue where high-priority tasks continuously arrive can starve low-priority tasks indefinitely. This is unacceptable in a banking platform—every task has an underlying obligation, and unbounded delay creates operational risk. We introduce an aging function ℬ(Δτ) that adds an incrementally growing bonus to any task that has been waiting beyond a threshold age:

Eq. (13) — Aging Bonus Function Anti-Starvation
ℬ(Δτ; μage, Bmax, Δτ0) = Bmax · (1 − e−μage · max(Δτ − Δτ0, 0))
Bmax — maximum aging bonus (caps the score inflation and sets the priority ceiling an aged task can reach); Δτ0 — aging onset delay (tasks do not age until they have waited at least Δτ0 hours, preventing thrashing of newly arrived tasks); μage — aging rate (1/μage is the characteristic age in hours at which 63% of the maximum bonus is awarded). The function is monotonically increasing from 0 at Δτ0 to Bmax asymptotically, guaranteeing every task is eventually processed.
Aging Bonus Curves — Bmax = 0.3, Δτ₀ = 2h, Varying μage
ℬ(Δτ) from Eq. (13) for four aging rates μage. The onset delay Δτ₀ = 2h means a task must wait at least 2 hours before accumulating any bonus. The asymptote Bmax = 0.30 ensures even a fully aged low-priority task cannot outrank a high-priority task that has just arrived with the maximum raw score.
ℬ(Δτ) = Bmax · (1 − exp(−μage · max(Δτ − Δτ₀, 0)))

Under the MDPQ policy with aging function ℬ satisfying Bmax > 0 and μage > 0, and assuming system stability (ρ < 1), every task in the queue is processed in finite expected time. Specifically, any task 𝒯 with score P(𝒯, τa) = P0 will reach priority class 1 within at most

Δτpromote ≤ Δτ0 − (1/μage) · ln(1 − (P1 − P0) / Bmax)

hours of waiting, where P1 is the minimum score threshold for class 1.

8. Priority Class Assignment

The continuous score P(𝒯, τ) is discretised into K priority classes via thresholds θ1 > θ2 > … > θK−1:

Eq. (14) — Priority Class Assignment
class(𝒯, τ) = k   ⟺   θk ≤ P(𝒯, τ) < θk−1
with θ0 = +∞ (class 1 is the highest priority) and θK = 0. Thresholds θk should be set such that, in steady state, the fraction of tasks in class 1 is at most ρ1 = 0.3 of total throughput—ensuring the highest-priority queue does not become oversaturated. This requires periodic empirical calibration of the thresholds against the observed score distribution.
Priority Score Landscape — 2D Isoscore Curves
Aggregate score P as a function of financial exposure (normalised) and remaining deadline, holding w₂=0.28, w₁=0.30, ω=0.5, δ=0.25/h, all other dimensions fixed at 0.5. Curves show iso-priority contours. Shaded bands correspond to priority classes 1–3. Model-derived from Eq. (8).
P = (1 + ωe−δΔt)(w₁f₁ + w₂f₂ + const.) with f₁ from Eq.(1), f₂ from Eq.(2)

9. System Stability and Throughput

For the MDPQ system to be stable, the standard non-preemptive priority queue condition must hold:

Eq. (15) — Stability Condition
ρ = Σk=1K λkc · μ̄ < 1
where c is the number of processors and μ̄ is the harmonic mean service rate across classes. Crucially, the priority discipline does not affect system stability—it only redistributes waiting time across classes. A system that is unstable under FIFO remains unstable under any priority policy.

Little's Law provides the fundamental throughput identity. For each priority class k in steady state:

Eq. (16) — Little's Law Per Priority Class
Lk = λk · (Wk + 1μk)
Lk — mean number of class-k tasks in the system (queue + service); Wk — mean waiting time from Eq. (10). The total queue length L = Σk Lk is invariant to priority ordering (it depends only on ρ), but the per-class distribution is controlled by the priority policy.
Mean Queue Length by Class vs Utilisation — Little's Law Decomposition
Lk = λk(Wk + 1/μk) for three classes from Eqs. (10) and (16). Equal arrival rates (λk = λ/3), μ = 2/h. Demonstrates how total queue length (dashed) is invariant while class-level lengths differ dramatically at high utilisation.
Lk = λk · Wk + ρk  (Little's Law, class k)

10. Implementation Architecture

The MDPQ model maps naturally to a priority heap implementation. At each scheduling cycle (configurable: 100ms to 5 minutes depending on throughput), all tasks in the waiting state are re-scored and the heap is rebuilt. This ensures that aging bonuses and deadline amplification are applied continuously rather than only at arrival.

Python — MDPQ scorer
import math
import heapq
from dataclasses import dataclass, field
from typing import Optional
import time as _time

class TaskType:
    RENEGOTIATION = "renegotiation"
    MANDATE_EXPIRY = "mandate_expiry"
    SEPA_RETURN    = "sepa_return"
    FRAUD_DISPUTE  = "fraud_dispute"
    NOSTRO_BREAK   = "nostro_break"

@dataclass
class Task:
    id: str
    arrival:       float          # Unix timestamp
    deadline:      float          # Unix timestamp; float('inf') if none
    amount:        float          # Exposure in base currency
    reg_level:     int            # Regulatory obligation 1–5
    cpty_tier:     int            # Counterparty tier 1–5
    n_dependents:  int = 0
    escalated:     bool = False
    task_type:     str = TaskType.RENEGOTIATION

class MDPQScorer:
    """Multi-Dimensional Priority Queue scorer (Eq. 8)."""

    def __init__(
        self,
        weights:   tuple[float,...] = (0.30, 0.28, 0.22, 0.12, 0.08),
        A0:        float = 1_000,
        A_max:     float = 5_000_000,
        alpha:     float = 1.5,    # Urgency curvature
        beta_h:    float = 4.0,    # Urgency horizon (hours)
        gamma:     float = 1.5,    # Regulatory convexity
        omega:     float = 0.5,    # Max deadline amplification
        delta:     float = 0.25,   # Amplification decay (1/h)
        B_max:     float = 0.30,   # Max aging bonus
        mu_age:    float = 0.05,   # Aging rate (1/h)
        age_onset: float = 2.0,    # Aging onset (hours)
        eta:       float = 5.0,    # Dependency half-saturation
        kappa:     float = 0.25,   # Escalation bonus
    ):
        self.w = weights
        self.A0, self.A_max = A0, A_max
        self.alpha, self.beta = alpha, beta_h * 3600   # convert to seconds
        self.gamma = gamma
        self.omega, self.delta = omega, delta / 3600
        self.B_max, self.mu_age = B_max, mu_age / 3600
        self.age_onset = age_onset * 3600
        self.eta, self.kappa = eta, kappa
        self._R_max = 5

    def _f1_financial(self, amount: float) -> float:
        return min(1.0, math.log1p(amount / self.A0) /
                        math.log1p(self.A_max / self.A0))

    def _f2_urgency(self, now: float, deadline: float) -> float:
        delta_t = max(deadline - now, 1e-3)          # Eq. (2)
        return 1.0 - math.exp(-self.alpha * self.beta / delta_t)

    def _f3_regulatory(self, r: int) -> float:           # Eq. (3)
        g = self.gamma
        return (math.exp(g * (r - 1)) - 1) / (math.exp(g * (self._R_max - 1)) - 1)

    def _f4_counterparty(self, c: int) -> float:          # Eq. (4)
        return math.log(self._R_max - c + 2) / math.log(self._R_max + 1)

    def _f5_dependency(self, n: int) -> float:             # Eq. (5)
        return 1.0 - 1.0 / (1.0 + n / self.eta)

    def score(self, task: Task, now: float) -> float:
        # Dimension scores
        f = [
            self._f1_financial(task.amount),
            self._f2_urgency(now, task.deadline),
            self._f3_regulatory(task.reg_level),
            self._f4_counterparty(task.cpty_tier),
            self._f5_dependency(task.n_dependents),
        ]
        raw = sum(self.w[i] * f[i] for i in range(5))

        # Deadline amplification Ω (Eq. 7)
        delta_t_h = (task.deadline - now) / 3600
        omega_t = 1.0 + self.omega * math.exp(-self.delta * (task.deadline - now))

        # Aging bonus ℬ (Eq. 13)
        age = now - task.arrival
        aging = self.B_max * (1.0 - math.exp(
            -self.mu_age * max(age - self.age_onset, 0)
        ))

        # Escalation bonus κε
        esc = self.kappa if task.escalated else 0.0

        return omega_t * raw + aging + esc   # Eq. (8)

    def assign_class(self, score: float,
                      thresholds: tuple = (0.75, 0.50, 0.30)) -> int:
        """Returns 1 (highest) to 4 (lowest). Eq. (14)."""
        for k, θ in enumerate(thresholds, start=1):
            if score >= θ: return k
        return len(thresholds) + 1

The scheduler wraps the scorer in a heap re-evaluation loop. Because P(𝒯, τ) is a function of the current time τ through f2, Ω, and ℬ, the effective priority of every task changes continuously. A naïve approach rebuilds the entire heap every cycle; a more efficient implementation tracks the maximum possible priority change rate per task (bounded by the derivatives of f2 and Ω) and only triggers re-evaluation when the change exceeds a configured epsilon—reducing scheduler overhead by an order of magnitude in typical operating conditions.

Score Derivative Bound for Selective Re-Evaluation

Eq. (17) — Bound on Score Rate of Change
| dP/dτ | ≤ Ωmax · w2 · α · βd − τ)2 · (1 − f2) + (1 + ω) · w2 · ∂f2∂τ + μage · Bmax
This bound allows the scheduler to compute, for each task, the maximum time before its score changes by more than ε from its last evaluated value. Tasks near their deadline have tighter bounds (higher rate of change) and require more frequent re-evaluation; tasks far from their deadline can be safely re-evaluated infrequently.