Learn
Lesson · Latency and the Tail · The tail

Tail Amplification under Fan-out

A request that fans out to n independent backends and waits for all of them is fast only if every one of them is fast. If each call is inside its own p99 with probability 0.99, then all n are with probability 0.99ⁿ. That is 0.499837 at n = 69: a service with a fan-out of sixty-nine misses its per-call p99 on most requests, and nothing anywhere in it is broken.

P(all n calls ≤ their p99) = 0.99ⁿ under independence P(at least one slow) = 1 − 0.99ⁿ n = 69 0.99⁶⁹ = 0.499837 a p99 has become the median n = 10 9.56% slow n = 100 63.40% slow break-even n: p90 → 7 p95 → 14 p99 → 69 p99.9 → 693
One multiplication, repeated n times

Core ideas

What this lesson establishes

The hard idea is a single exponent, and the reason it is hard is that the arithmetic is trivial and the conclusion is not one most people will believe before seeing it.

1

Waiting for all of them means every one must be fast

A request that issues n calls in parallel and needs all the answers finishes when the slowest returns. So “this request was fast” is the conjunction of n separate statements, and a conjunction of independent events multiplies: p × p × … × p = pⁿ.

2

0.99ⁿ reaches one half at n = 69

0.99⁶⁹ = 0.499837, just under a half, and 0.99⁶⁸ = 0.504886, just over. So at a fan-out of sixty-nine, more than half of all requests contain at least one call outside its p99. The per-call p99 is now the whole request’s median, which is a statement about arithmetic rather than about anything being wrong.

3

The break-even n is set by the per-call percentile

A p90 per call breaks even at n = 7, a p95 at n = 14, a p99 at n = 69 and a p99.9 at n = 693. Each step of a factor of ten in the per-call tail buys roughly a factor of ten in the fan-out you can afford, which is the only lever there is apart from not fanning out.

The material

One multiplication, and what it does to a fan-out

The exponent, the number sixty-nine, and the assumption the whole thing rests on.

A search page assembles itself from many services: one for results, one for advertisements, one for spelling, one for each of several personalisation signals, and a shard of the index for each partition of the corpus. They run in parallel, which is the right design — by the max rule of “Serial Sums, Parallel Maxes” the group costs what the slowest member costs rather than the sum. The question is what the slowest member costs.

Theorem · Fan-out amplification

Let a request issue n calls that are independent, and let each call complete within its own q-th percentile with probability p = q. Then the probability that every call is inside its percentile is pⁿ, and the probability that at least one is outside it is 1 − pⁿ.

The n at which pⁿ = ½ is the fan-out width at which the per-call q-th percentile has become the whole request’s median: half of all requests contain a call beyond it.

The proof is one line — independent events multiply — and the content is entirely in the numbers it produces.

p = 0.99 n = 1 0.99¹ = 0.990000 1.00% of requests contain a slow call n = 10 0.99¹⁰ = 0.904382 9.56% n = 50 0.99⁵⁰ = 0.605006 39.50% n = 68 0.99⁶⁸ = 0.504886 49.51% n = 69 0.99⁶⁹ = 0.499837 50.02% ← the break-even n = 100 0.99¹⁰⁰ = 0.366032 63.40% n = 200 0.99²⁰⁰ = 0.133980 86.60%

Read the n = 100 row slowly. Every backend is meeting its latency objective, every dashboard is green, nobody is paged — and 63.40% of requests are waiting on a call that is outside the objective. There is no failure here to find, because there is no failure. The system is doing exactly what it was specified to do.

What it takes to move the number

  • a per-call p90 breaks even at n = 7
  • a per-call p95 breaks even at n = 14
  • a per-call p99 breaks even at n = 69
  • a per-call p99.9 breaks even at n = 693

Those four rows are the whole strategy space. Reduce the fan-out, or push the per-call tail down by a factor of ten to buy a factor of ten in width, or stop requiring every answer — a request that can return with nine of ten results has changed the conjunction and is no longer in this arithmetic at all. There is also the option “Hedged Requests” takes, which is to change the per-call tail without changing the per-call service.

Example · Two hundred shards at a p99.9

Push every call to a p99.9 — an expensive, real engineering achievement — and the break-even moves to n = 693. At a fan-out of 200 the probability that every call is inside its p99.9 is 0.999²⁰⁰, about 0.819, so 18% of requests still contain a slow call. That is a far better place to be than the 86.60% the same fan-out gives at a p99, and it is not zero and never will be.

Everything above assumes independence, and it is worth being precise about which direction reality departs from it. Real slowness has shared causes: a garbage-collection pause on a host that several calls land on, a saturated switch, a hot shard. Shared causes make slow calls arrive together, so fewer requests contain a slow call than 1 − pⁿ predicts — and the ones that do contain several. Independence is the assumption that spreads the damage as thinly and as widely as possible, and the real distribution is lumpier than it.

The misconception to name is the comfortable one: “each call is fast at its p99, so the request is.” The premise is about one call and the conclusion is about n of them, and the step between them is a multiplication that nobody performs because it does not look like there is anything to compute.

Interactive

What a fan-out does to a tail

pⁿ, and the width at which a per-call p99 becomes the request's median

Tail amplification under fan-outP(all n calls land inside their own percentile) = pⁿ
P(at least one slow)your fan-outbreak-even n

Method

Sizing a fan-out

Four steps, and the third is the one that turns a design review around.

1

Count the calls the request waits for

Only the ones it needs before it can answer. A call whose result is optional, or one that is fired and forgotten, is not in n. Shards count individually: a query against forty partitions is a fan-out of forty.

2

Raise the per-call percentile to that power

pⁿ is the probability that every call is inside its percentile. 1 − pⁿ is the probability that the request contains at least one that is not, which is the number worth quoting to anyone.

3

Find the n at which pⁿ falls to a half

That is the width at which the per-call percentile has become the request’s median. Compare it with the fan-out you actually have; if yours is larger, the per-call objective is no longer describing your users’ experience.

4

Choose among the three levers, or change the question

Reduce n, reduce the per-call tail by a factor of ten per factor of ten in width, or stop waiting for every answer. If none is available, the remaining move is to hedge, which buys tail without buying service.

Fan-out arithmetic

Score 0 / 0

A fan-out of 100 at a per-call p99

A hundred shards, each meeting a p99 objective, and a request that needs all hundred answers.

per call p = 0.99 (each call is inside its p99 with prob 0.99) fan-out n = 100 P(all fast) = 0.99¹⁰⁰ = 0.366032 P(one or more slow) = 1 − 0.366032 = 0.633968 → 63.40% where is the break-even? 0.99⁶⁸ = 0.504886 > ½ 0.99⁶⁹ = 0.499837 < ½ → n = 69 so at n = 100 the request is well past the point at which the per-call p99 became the request's median. what would fix it? n → 69 at p99 still half the requests p → 0.999 at n = 100 0.999¹⁰⁰ = 0.904792 → 9.52% slow stop needing all 100 answers → different arithmetic entirely

The third option is the one that gets used in practice, and it is worth seeing why it is not a cheat. Returning with ninety-five of a hundred shard results changes the event whose probability is being computed: the request no longer needs a conjunction of a hundred statements, so there is no pⁿ to compute. The cost is an answer that is slightly incomplete, and the whole design question is whether anyone can tell.

It is also worth noticing how little the second option buys per unit of effort. Moving every call from a p99 to a p99.9 is an order-of-magnitude reduction in the tail, and at n = 100 it takes the slow-request rate from 63.40% to 9.52% — a real improvement, and still not a number anyone would put on a slide.

For a faded rehearsal, take a fan-out of 40 with a per-call p95. The supplied first move is the break-even for a p95, which the lab prints as n = 14. Say whether 40 is past it, compute 0.95⁴⁰ and the slow-request probability, then say which of the lab’s four per-call percentiles brings that probability under ten percent at the same width. Check each figure in the lab before opening the quiz.

Common mistakes

1
Reasoning from one call to the request“Each call is fast at its p99” is a statement about one call. “The request is fast” requires all n to be, and the step between them is pⁿ. It is invisible because there is no obvious place in the sentence where a multiplication belongs.
2
Adding the per-call tail probabilitiesn × 1% is close for small n and wrong for large: at n = 10 it gives 10% against the true 9.56%, and at n = 200 it gives 200%. It overstates because it counts a request with two slow calls twice. 1 − pⁿ is the figure, and it never exceeds one.
3
Forgetting that independence is an assumption, and which way it failsShared causes make slow calls cluster, so fewer requests are affected than 1 − pⁿ says and the affected ones are worse. 1 − pⁿ is therefore the widest-spread case rather than the worst case, and a system whose slow requests arrive in bursts is telling you the calls were never independent.

Check your understanding

✓
Finish when a fan-out width makes you reach for an exponent.

You should be able to compute pⁿ and 1 − pⁿ for a described fan-out, locate the break-even n for a given per-call percentile, and say which of the three levers — width, per-call tail, or not waiting for everything — a particular system has available.

Note: The fan-out made the tail worse by composing independent calls. “Hedged Requests” composes two independent copies of the same call and makes the tail better by the same mechanism, squaring a tail probability instead of raising a success probability to a power. The two labs are worth reading in one sitting: they are one fact about independence, pointed in opposite directions.

Kept in this browser only, for you. Nothing is sent anywhere and nothing checks it. Carry it to another device.

Feedback and recommendations

Something to change about this lesson? Write it down, tick it off when it is handled, and export the list when you want to act on it. Kept in this browser only: nothing is sent anywhere, and nobody is notified.

No recommendations yet for this lesson.