skip to content

Why does serving the shortest support tickets first minimize total waiting time, when a colleague says order barely matters?

level: seniorimportance: should knowfreq 42%

answer

  1. ask who else pays for a long ticket
  2. count the tickets waiting behind each one
  3. the queue empties at the same moment regardless
  4. durations multiplied by remaining queue length
  5. largest multiplier onto the smallest duration

basics

~20 s

Each ticket's handling time is re-paid by everyone still queued behind it, so serving a long one early multiplies its cost. Shortest-first keeps the big multipliers on the small durations, and the remaining queue is the same problem again.

solid answer

~50 s

The skeptic is right about one thing and wrong about the metric. With one agent and every ticket already waiting, the *last* ticket finishes at the same moment in every order — total handling time is fixed. What order changes is the sum of individual waits, because a ticket's duration is re-paid by every ticket still behind it. Serving a duration of `d` with `k` tickets queued behind adds `d` to each of their waits, so the objective is a sum of durations weighted by how many follow. Shortest-first puts the largest multipliers on the smallest durations. Three tickets of 1, 2 and 30 minutes give completion times summing to 37 shortest-first and 95 longest-first — not a rounding difference. And after the first pick, the remaining queue is the identical problem, so the same rule applies down the line.

code

pseudocode · 8 lines
pseudocode
// q[0..n-1] = handling times in the chosen serving order
elapsed = 0
total = 0
for i in 0..n-1:
    elapsed = elapsed + q[i]
    total = total + elapsed
// elapsed = when the queue empties (same for every order)
// total   = sum of resolution times (order-dependent)

go deeper

for a junior

Remember the shape of the answer: a long item served early makes everyone behind it wait longer, so the total of individual waits depends on order even though the same total work is done.

for a middle

Explain the decomposition — each duration is multiplied by how many items remain behind it — and derive from it why the largest multiplier should land on the smallest duration.

for a senior

Separate the two metrics before arguing, bring numbers, and name the model assumptions: one server, everything present at the start, no weights, no preemption. Then say which of those your real queue violates.

for a principal

Own the objective itself. Decide whether the organisation is optimising mean wait, tail latency or a business-weighted mix, and defend the fairness guard that keeps long work from starving even at a cost to the headline average.

## Why the intuition fails The objection — *the same work gets done either way, so what does order change?* — is a correct statement about the wrong quantity. Two different metrics are being conflated: - **Makespan**, the moment the queue is finally empty. With a single agent, every ticket present from the start, and no preemption, this is just the sum of all durations. **Order cannot change it.** The skeptic's intuition is exactly right here. - **Total (or mean) time in system**, the sum over tickets of how long each one waited from arrival to resolution. **Order changes this enormously.** When you argue this out loud, concede the first point immediately and then move the discussion to the second. Half the disagreements about scheduling are two people optimising different objectives without noticing. ## The cost decomposition Serve the tickets in some order and accumulate: ``` // q[0..n-1] = handling times in the chosen serving order elapsed = 0 total = 0 for i in 0..n-1: elapsed = elapsed + q[i] total = total + elapsed ``` `elapsed` after step `i` is when ticket `i` is resolved, and `total` is the sum of those resolution times. Because `total` sums prefix sums, the duration at position `i` appears in every later term as well — it is counted once for its own ticket and once for each ticket still behind it. Written the other way round: a ticket served with `k` others still queued contributes `duration x (k + 1)` to the objective. That single sentence settles the design. The objective is a sum of durations multiplied by remaining-queue-lengths; the multipliers are fixed by position (n, n-1, ... , 1); you get to choose which duration receives which multiplier. To minimise a sum of products where one list of factors is fixed, pair the largest multiplier with the smallest value — the biggest multiplier goes to the shortest ticket. That *is* shortest-handling-time-first. ## Numbers for the skeptic Durations of 1, 2 and 30 minutes, one agent, all waiting at the start: | Order | Resolution times | Sum | Mean wait | |---|---|---|---| | 1, 2, 30 | 1, 3, 33 | **37** | 12.3 min | | 30, 2, 1 | 30, 32, 33 | **95** | 31.7 min | The queue empties at minute 33 in both. Mean customer wait differs by a factor of 2.6. "Roughly the same" is not a defensible description of that gap, and the gap widens as one long ticket sits in front of more short ones. ## The two properties, made explicit This is a leaf-level greedy, so name both properties rather than waving at "it's obviously best": - **Greedy-choice property.** There is an optimal schedule that begins with a shortest ticket. Intuition from the decomposition: the first position carries the largest multiplier, `n`, so whatever sits there is amplified the most; giving that slot to anything longer than the minimum inflates the total. - **Optimal substructure.** After the first ticket is served, the remaining k-1 tickets form the same problem — one agent, all present, minimise the sum of their resolution times — shifted by a constant offset that is the same for every ordering of the remainder and therefore cannot change which remainder-ordering is best. So the optimal schedule is a shortest ticket followed by an optimal schedule of the rest. Both together are what let you commit to the first pick and recurse, which in practice means: order by duration ascending and serve. ## Where the guarantee ends — the part a senior is expected to raise The result holds for a specific model, and real queues violate it constantly: - **Tickets arrive over time.** With release times, a shortest ticket may not exist yet, and the non-preemptive problem becomes genuinely hard; shortest-first is then a heuristic. - **Tickets have different business weight.** If a ticket carries an importance factor, the right greedy orders by weight-to-duration ratio, not duration alone. Sorting on duration is then simply the wrong key. - **Several agents, or preemption.** Different model, different analysis. - **Fairness and starvation.** Under continuous arrivals of short work, a long ticket can be deferred indefinitely. This is the argument that actually wins meetings: pure shortest-first optimises a total while quietly destroying the tail. Production queues bound it — age the waiting time into the priority, or reserve capacity for a long-ticket class — and accept a slightly worse total for a bounded worst case. And know what the rule does *not* claim. It does not shorten the day, it does not minimise the longest single wait (it typically makes that worse), and it does not survive a change of objective. Optimal is always optimal *for a stated objective under a stated model*, and naming both is what makes the answer senior rather than clever.

  • Does shortest-first also empty the queue sooner?
    No, and conceding that strengthens your case. With one agent and all tickets present, the last one finishes after the sum of all durations no matter what order you choose. Only the distribution of individual waits moves, which is exactly why the total-wait metric has to be named explicitly before arguing about order.
  • What change to the setup breaks the optimality of shortest-first?
    Release times are the big one: if tickets arrive over time, a short ticket may not be available when the agent is free, and the non-preemptive version becomes genuinely hard. Business weights break it differently — the right key becomes the weight-to-duration ratio rather than duration alone.
  • Would you actually run pure shortest-first in a support queue?
    Not unguarded. It optimises a total while allowing long tickets to be starved indefinitely under a steady flow of short ones. Real queues bound the tail: age waiting time into the priority, or reserve agent capacity for a long-work class, accepting a modestly worse total for a bounded worst case.

A long ticket at the front of the queue is like a slow vehicle at the head of a single-lane road: it loses only its own time, but everyone behind it pays the same delay over again.

saying these in an interview costs you the question

  • Order does not matter because the same work is done
  • Shortest-first also finishes the whole queue sooner
  • It minimizes the longest individual wait
  • It stays optimal once tickets arrive at different times
  • This is just sorting; no correctness argument is needed

context