The lab’s preset is a hundred measured calls, given as run lengths: forty at 10 ms, twenty-five at 12 ms, fifteen at 15 ms, ten at 20 ms, five at 30 ms, three at 50 ms, one at 120 ms and one at 300 ms. Its median is 12 ms, its p95 is 30 ms and its p99 is 120 ms — a tail ten times the median, which is an ordinary shape for a service that is not in trouble.
Definition · Hedged requestA hedged request with delay d issues a second, independent copy of the call if the first has not answered within d, and completes when either copy answers. Its completion time is min(X, d + Y), where X and Y are independent draws from the service’s latency distribution. The extra load it creates is P(X > d): the fraction of requests that live long enough to trigger the copy.
The tail of the hedged request factorises. It exceeds t only if the first copy is still running at t and the second copy, which started at d, is still running at t. Those are independent, so their probabilities multiply:
P(hedged > t) = P(X > t) · P(X > t − d)
d = 30 ms, the p95 of the service
extra load = P(X > 30) = 5/100 = 1/20 = 5.0%
just past d = P(X > 30)·P(X > 0) ≈ 1/20 (one copy only)
at t = 42 = P(X > 42)·P(X > 12) = (1/20)(7/20) = 7/400
at t = 45 = P(X > 45)·P(X > 15) = 1/100
hedged p99 = 45 ms unhedged p99 = 120 ms
hedged p50 = 12 ms unhedged p50 = 12 ms
Two things happened and only one of them was asked for. The p99 fell from 120 ms to 45 ms, a reduction of 62%, for five percent more traffic. The median did not move at all — it is still 12 ms — because ninety-five percent of requests never reach the delay and never trigger anything. A hedge is a tail instrument. It does not make a service faster; it makes a service less occasionally awful.
Choosing the delay
- d = 12 ms, the median — load +35.0%, hedged p99 30 ms
- d = 20 ms — load +10.0%, hedged p99 35 ms
- d = 30 ms, the p95 — load +5.0%, hedged p99 45 ms
- d = 50 ms — load +2.0%, hedged p99 62 ms
- d = 120 ms, the p99 — load +1.0%, hedged p99 120 ms
The list is the whole design decision. Hedging at the median buys 15 ms more of tail reduction than hedging at the p95 and costs seven times the extra traffic to get it. Hedging at the p99 costs almost nothing and achieves almost nothing, because by 120 ms the only requests left running are the ones whose second copy will not finish in time either. Somewhere around the p95 is where the curve bends, which is why that is the usual recommendation.
Example · Why the extra load is not a rounding errorA service handling 40 000 requests a second at a 5% hedge rate sends an extra 2000 calls a second. That is real capacity, it must be provisioned, and it arrives precisely when the service is already having difficulty — the requests that trigger hedges are the slow ones, and slowness is correlated in time. A hedge that is not capacity-planned adds load to a system at the exact moment load is what is wrong with it.
That last observation is also the limit of the technique, and it is worth stating as sharply as possible. Every number on this page assumes the second copy is independent of the first. If the call is slow because the request is expensive — a large query, a cold cache entry, a user with a great deal of data — then the second copy is expensive in exactly the same way and P(both slow) is not p² but something close to p. The hedge then costs its extra load and buys nothing.
Independence is plausible when the slowness belongs to the server: a garbage-collection pause, a scheduling delay, a disk that is briefly busy. It is implausible when the slowness belongs to the request, and it is worse than implausible when the second copy is routed to the same replica, which makes the two copies the same draw. Hedging to a different replica is not a refinement of the technique; it is a condition for the arithmetic being about anything.