Interactive tool
How long do your retries actually take?
Retries get configured as three small numbers, and the one that matters is none of them. Six attempts, one second base, doubling, looks modest and takes 31 seconds — which is one second longer than a gateway that gives up at 30. This works out the number you actually have to budget for.
Runs in your browser · nothing is sent anywhere
The wait before the first retry.
2 doubles each time. 1 is a constant delay.
Ceiling for any single wait.
Including the first call, so waits = attempts − 1.
Worst case, every attempt fails
15s
This is the number every timeout above this code has to be larger than. With full jitter the average is about 7.5s, but you should budget for the worst case rather than the average.
| Attempt | Wait before it | Elapsed |
|---|---|---|
| 1the call itself | — | 0ms |
| 2 | 1s | 1s |
| 3 | 2s | 3s |
| 4 | 4s | 7s |
| 5 | 8s | 15s |
Related troubleshooting
What a backoff is
When a call fails, retrying immediately is usually the worst option: whatever was wrong has had no time to get better, and your retry adds to the load that may have caused it. So you wait, and you wait longer each time. That is a backoff.
The waits are described by three numbers — how long the first one is, what each is multiplied by, and how many attempts you make. What none of those three tells you is how long the whole thing takes, which is the number everything else has to accommodate.
Using it
Put in the three numbers your code uses and read the total. Then compare it against the shortest timeout above this call — the HTTP client, the gateway, the load balancer, the user’s patience. If the total is larger than any of them, the retries outlive the thing waiting for them.
The table shows the wait before each attempt and the running total, so you can see where the cap starts flattening the curve.
Why jitter is not optional
A backoff spreads retries across time. It does not spread them across clients. A thousand callers that failed at the same instant, all waiting exactly one second, retry at the same instant — so the second wave is the same size as the first, and the third is the same size again. The dependency gets no quieter, it just gets hit in pulses.
Jitter fixes that by randomising each wait. Full jitter picks uniformly between zero and the delay, which spreads hardest and averages half the wait. Equal jitter keeps half the delay fixed and randomises the rest, which spreads a little less and guarantees a minimum gap. Decorrelated derives each wait from the previous one rather than from the attempt number.
Budget on the worst case rather than the average. Jitter lowers the expected total and does nothing to the maximum, and the maximum is what has to fit inside the timeout above you.
Tools that go with this
- Error Budget CalculatorWhat an availability target allows, and the burn rate.
- On-Call Load AssessmentYour paging numbers against published thresholds — Google SRE's 2 per shift, the 30–50% actionable band, DORA recovery tiers.
- HTTP Status Code ExplainerWhat a status code means, and whether your app or the proxy in front of it sent it.
- Container Exit Code ExplainerWhat 137, 143 and 139 mean, and the rule behind them.
Questions people ask about this
How many retries should I use?
Fewer than you think, and chosen by working backwards from the time you have rather than by picking a round number. Decide the longest the caller can wait, subtract the time one attempt takes, and see how many waits fit.
Three to five attempts covers most transient failures. Beyond that you are usually not retrying a blip — you are queueing against an outage, and the honest response is to fail and let the caller decide.
Why does my retry make the outage worse?
Because every client is retrying too. A dependency that is struggling receives its normal traffic plus everyone’s retries, which is the load that tips it from slow to down.
Jitter helps by spreading the waves. A circuit breaker helps more: once failures cross a threshold it stops calling altogether for a while, which is the only thing that actually reduces load rather than rearranging it.
Should I retry every failure?
No, and retrying the wrong ones is a common source of duplicate work. Retry what might succeed next time: timeouts, connection failures, 429 and most 5xx.
Do not retry a 400, a 401 or a 404 — the answer will be the same. And be careful retrying anything that is not idempotent: a payment that timed out may well have succeeded, and the retry charges twice.
What does the cap actually do?
It stops the delay growing without bound. With a multiplier of 2 and no cap, the eighth wait is 128 times the first, which is usually longer than anyone is prepared to wait.
Once the cap binds, the schedule becomes a constant delay at that value — so a low cap with many attempts is a fixed-rate retry wearing an exponential costume. The table marks where that starts.
Does Retry-After override my backoff?
Yes, and it should. When a server sends Retry-After it is telling you when capacity actually returns, which is better information than your formula has.
Honour it, and keep your own jitter on top so that every client told the same number does not return in the same instant.
Did this get you to an answer?
No text box on purpose — please do not paste production logs anywhere