Retry, Jitter & Backoff
The exponential-backoff formula, why jitter is mandatory, and AWS's "full jitter" recommendation.
Overview
Retries: simple idea, subtle implementation
Retries are the most common cause of cascading failure. The intuition, "if a request fails, try again," is fine; the implementation is subtle.
> [!IMPORTANT] Retry only idempotent operations, bound the attempts, and always add jitter.
The three knobs
- 1. Retry count — Bounded or unlimited — Bounded, typically 2-3 attempts; unlimited retries cause retry storms
- 2. Backoff — Linear (N s x attempt, slow ramp), exponential (base × 2^attempt, standard), fixed (rarely correct) — Exponential
- 3. Jitter — None or random — Without jitter all clients retry together, a thundering herd; with jitter retries spread out
Backoff formulas
- Plain exponential — wait = base × 2^attempt — 100ms, 200ms, 400ms, 800ms, 1600ms
- Full Jitter (AWS recommendation) — wait = random(0, base × 2^attempt) — random(0, 100ms), random(0, 200ms), random(0, 400ms), ...
- Equal Jitter — wait = (base × 2^attempt / 2) + random(0, base × 2^attempt / 2) — 50-100ms, 100-200ms, 200-400ms; slower than full jitter, same spreading
- Decorrelated Jitter (AWS) — wait = min(cap, random(base, prev × 3)) — 100, then 100-300, then 100-900; slightly faster but harder to reason about
The AWS Architecture Blog post "Exponential Backoff and Jitter" found that random offsets reduce load on the failing service. Full jitter spreads retries best.
The retry-storm anti-pattern
A service is degraded for 5 seconds. With naive backoff, 10,000 clients retry at exactly T+200ms, then T+400ms, and each pulse is larger than the original load. Every backoff window ends with another tsunami of requests.
Idempotency requirement
- Idempotent — Same result no matter how many times it runs — PUT /users/123 sets state; GET reads
- Non-idempotent — Each call has a side effect — POST /payments charges; POST /tweets posts
- Idempotency keys — Client generates a unique key; server deduplicates by it
- Conditional updates — If-Match headers proceed only if state is unchanged
- Do not retry — For some financial operations, fail and let the user retry manually
Where to retry
- Client side: browser, mobile, internal service client — Network failures, 5xx, 429
- Service side: proxies and gateways — Transient errors such as network and timeout, not application errors like most 4xx
- Anti-pattern — Retrying on the same proxy that made the original call amplifies load on the same path
HTTP retry guidance
- 5xx, except 501 and 505 — Retry; the server says it is temporary
- 429 Too Many Requests — Retry per the Retry-After header
- 408 Request Timeout — Retry
- Other 4xx — Do not retry; it is a client error and will repeat
- Network errors: ECONNRESET, timeout — Retry
- 3xx redirects — Follow, do not retry
The retry budget
A service should have a global retry budget: at most N retries per second across all clients. Without one, retries during an incident can saturate even healthy capacity.
Key concepts
- Exponential backoff
- wait = base × 2^attempt. Standard formula. NEVER use without jitter.
- Full Jitter (AWS)
- wait = random(0, base × 2^attempt). Mathematically optimal for spreading retries. Industry standard.
- Retry storm
- Synchronized retries multiply load on a recovering service; prevent it from recovering. Solved by jitter.
- Idempotency
- Operation can be retried safely. Required for retries; non-idempotent ops need idempotency keys or no retry.
- Retry budget
- Global cap on retries per second. Token bucket. Prevents retry waves from exhausting healthy capacity.
- Bounded retries
- 2-3 attempts max. Unbounded is the canonical retry-storm cause.
When to use it
- Designing every retry policy — explicit jitter is non-negotiable
- Reviewing existing retries — are they bounded, jittered, idempotent?
- Postmortem with retry-storm component — was the policy correct?
- Service mesh / API gateway config — global retry settings affect every service
Interview questions
- Why is jitter mandatory for retries?
- How do you handle retries for non-idempotent operations?
- What's a "retry budget" and when do you need one?
Sign up free to read the full topic
More SRE topics
Start free on Cariara · Coding problems · System design studio