Idempotency & Retry-Safe Systems · Retries Done Right

Exponential Backoff and Jitter

Space out retries so recovering systems aren't flattened.

Immediate retries hammer a struggling dependency. Use exponential backoff (base × 2^attempt, capped) and jitter (randomization) so clients don't retry in synchronized waves. AWS's analysis shows full jitter (sleep = random(0, min(cap, base·2^n))) or decorrelated jitter spread load best. Cap attempts and total time, and honor server hints (Retry-After).

Backoff strategies

Strategy Load on recovering service Completion time
Immediate retry Worst (synchronized spikes) Fast when it works
Fixed delay Bad (synchronized waves) Predictable
Exponential, no jitter Better but clustered Grows quickly
Exponential + full jitter Best spread Good
Decorrelated jitter Very good Good
import random

def full_jitter(attempt: int, base: float = 0.1, cap: float = 10.0) -> float:
    return random.uniform(0, min(cap, base * 2 ** attempt))

async def with_retries(op, attempts=4):
    for n in range(attempts):
        try:
            return await op()
        except Retryable as e:
            if n == attempts - 1:
                raise
            await asyncio.sleep(e.retry_after or full_jitter(n))

Common pitfalls

  • No cap on the backoff or attempts.
  • Jitter omitted in fleets of clients.
  • Retrying non-retryable errors.

Key points

  • Exponential backoff with full jitter
  • Cap attempts and total time
  • Honor Retry-After

Further reading: AWS: Exponential backoff and jitter

Practice questions

Why add jitter to exponential backoff?

Answer

Without randomness, clients that failed together retry together, creating synchronized load spikes; jitter spreads retries over time.

What is full jitter?

Answer

Choosing the sleep uniformly at random between 0 and the capped exponential backoff value for that attempt.

Open in the app to mark lessons complete, take notes and track your progress.