Retry With Backoff and Jitter: The Version I Copy Everywhere
Description and use
Naive retry loops cause retry storms that worsen outages. Exponential backoff with full jitter, capped delays, and selective retryable errors spreads retries, respects server guidance, and prevents duplicate side effects.
Problem
Naive retry loops cause retry storms that worsen outages by hammering recovering services and synchronizing retries across many clients.
Outcome
The retry function limits load spikes, spreads retries over time, respects server guidance via Retry-After, and prevents duplicate side effects with idempotency keys.
Workflow
- Define retryable status codes (429, 502, 503, 504).
- Implement sleep(ms) returning a Promise that resolves after ms.
- Create retry(fn, opts) that loops: try fn(); on error, determine status; if retryable, compute cap=min(maxDelay, base*2^attempt); delay=random(0,cap); await sleep(delay); increment attempt; stop after max attempts.
- Use Retry-After header for 429 when present.
- Add idempotency key for non‑idempotent writes (POST) to avoid duplicate side effects.
- Wrap API calls with retry(fn, opts).
Evidence
Naive retries hammer a recovering server and turn blips into outages
Full jitter spreads retries so clients stop firing in sync
Retry 429 and 503, never 400 or 401, and respect idempotency
cap = min(maxDelay, base * 2^attempt) delay = random(0, cap)
- Record date: 2026-10-14T21:56:10.274Z