A service can look perfectly healthy in isolation and still feel slow to users.
Assume one backend has:
- normal latency: ~10ms
- p99 latency: 1s
That sounds acceptable. Only 1% of requests are slow.
Now imagine one user request fans out to 100 backend servers in parallel and cannot finish until every response comes back.
The probability that all 100 servers respond inside their p99 is:
0.99^100 ≈ 0.366
Which means the probability that at least one server is slow is:
1 - 0.99^100 ≈ 63%
So a latency event that happens only 1% of the time on one machine now affects roughly 63% of user requests.
This is the core idea behind tail latency at scale.
Why fan-out makes tail latency worse
In distributed systems, latency is often determined by the slowest dependency.
Consider an API that does this:
request | +--> shard 1 +--> shard 2 +--> shard 3 | ... | +--> shard 100 wait for all responses
Ninety-nine servers may respond in 10ms. If one server takes 1 second, the entire request takes 1 second.
The problem is not necessarily average latency. The problem is the probability that one component becomes a straggler. As fan-out increases, encountering a straggler becomes increasingly likely.
Hedged requests
One mitigation described in Google's The Tail at Scale paper is hedged requests.
Instead of immediately sending every request twice, you wait for some latency threshold:
send request -> replica A wait 50ms if response arrived: return it otherwise: send same request -> replica B take whichever response finishes first cancel the other
The important part is the delay. If most requests finish quickly, no duplicate is sent. Only requests entering the latency tail create additional work.
You are not making the slow server faster. You are simply giving yourself another chance to avoid waiting for it.
What this looks like in Go
Conceptually, the client behaves like this:
go1go request(replicaA) 2 3select { 4case result := <-response: 5 return result 6 7case <-time.After(hedgeDelay): 8 go request(replicaB) 9} 10 11return <-firstSuccessfulResponse
Production implementations need more care around cancellation, retries, timeouts, idempotency, and connection limits, but the idea is surprisingly small.
The trade-off
Hedging is not free. Duplicate requests increase backend traffic. If you hedge aggressively, a latency problem can turn into a load problem:
slow backend -> more hedged requests -> more backend load -> backend becomes slower -> even more hedging
That is why systems normally hedge only after something like the p95 or p99 latency threshold rather than duplicating every request immediately.
Hedging also works best for operations that are safe to repeat, particularly reads or properly idempotent requests.
The larger lesson
Distributed systems change probability.
A failure mode that looks rare on one machine may become normal once a request depends on dozens or hundreds of machines. That applies to more than latency:
more dependencies -> more chances for one dependency to misbehave -> worse end-to-end reliability
So when designing highly parallel systems, don't only ask:
What is the latency of one server?
Ask:
What happens to the user when their request depends on 100 of them?
That difference is where tail latency becomes a systems problem.
