top of page

Exponential Backoff

  • Writer: Pradeep P
    Pradeep P
  • 3 days ago
  • 3 min read

Layer 3 · Post 3 of 14

← Previous: Retries → Next: Idempotency

Layer 3 — Reliability · Post 28 of 88

Exponential backoff waits longer after each failed retry so a struggling service gets room to recover instead of being hammered.

What you'll learn

  • Why immediate retries keep a sick service sick

  • How exponential delays plus a cap actually look in numbers

  • Why jitter is not optional if thousands of clients retry together

The idea in one minute

You already decided to retry. Exponential backoff is the schedule: wait longer after each failure.

try 1 fail wait ~100 ms try 2 fail wait ~200 ms try 3 fail wait ~400 ms ... cap at e.g. 30 s, then DLQ or give up

The sick service gets gaps. Your client still recovers from blips (short wait) without becoming a denial-of-service bot (constant hammer).

Jitter means you add randomness so everyone does not wake up on the same millisecond.

Why it matters

Retries without delay are a thundering herd. Payments fails for 2 seconds. Every checkout in flight retries immediately. Payments comes back and is instantly crushed by the backlog of retries plus new traffic. It falls over again. You turned a blip into a sawtooth outage.

This is why AWS's architecture blogs treat backoff-plus-jitter as a default, not a nicety. Interviewers expect the phrase. They also expect you to cap it: unbounded exponential wait is how a webhook sits in a loop for hours on a 400 you should have dropped.

How it works

A common formula:

  • delay = min(cap, base * 2^attempt)

  • then delay = delay * random(0.5, 1.5) (or "full jitter": random(0, delay))

Example with base = 100 ms, cap 2 s:

  • After 1st fail: ~100 ms

  • After 2nd: ~200 ms

  • After 3rd: ~400 ms

  • After 4th: ~800 ms

  • After 5th: ~1.6 s

  • After 6th: cap at 2 s

On the user-facing request path, you rarely go past 2–3 attempts. The exponential curve is mostly for workers: SQS, webhook deliveries, connecting to a database at process start.

Respect Retry-After on 429. Their number beats your formula. That is rate limiting talking to you (a few posts from now).

Backoff is not a substitute for a circuit breaker. If the dependency is hard-down, waiting 100, 200, 400 ms still spends your timeout budget. Breakers fail fast without those tries. Use both: breakers to stop calling, backoff for the calls you still make.

A simple example

You send Stripe webhooks (Post 25). Their URL returns 500.

  • Immediate retry: you DDoS a customer who is deploying.

  • Exponential backoff over minutes, then hours, with a cap and a give-up: they get room to finish the deploy; you eventually dead-letter and page a human.

Same pattern for "cannot reach Postgres at boot." Kubernetes CrashLoopBackOff is exponential backoff for processes. Without it, a bad config restart-storms the node.

Common mistakes

No jitter. 10,000 lambdas time out together, sleep 1 s, retry together. You built a metronome.

No cap. 2^n becomes hours, then days, while a poison message is still wrong.

Backoff on the request path that exceeds the user timeout. The user already got 504. Your extra retries run for a ghost.

Linear retry ("every 1 s") for a dependency that is down for a minute. You still hit it 60 times per client. Exponential is the default; linear is for when you want a steady probe (health checks), not for user retries.

Treating backoff as fairness. It slows you. It does not magically shed load unless clients also stop sending new work (backpressure, rate limits).

How this shows up in real systems

  • AWS SDK, Google Cloud client libraries, Azure SDKs: exponential backoff with jitter is the default retry policy.

  • Kubernetes: CrashLoopBackOff, and controllers requeue with backoff.

  • Twilio / Stripe / GitHub webhook deliveries: retry windows measured in hours, not milliseconds.

  • Envoy retry backoff and gRPC retry policy (initialBackoff, maxBackoff, backoffMultiplier).

Recap

  • After each failed retry, wait longer, up to a cap.

  • Add jitter or synchronized clients become a stampede.

  • Request-path retries stay few and short; workers can back off for a long time — then you need idempotency.

Layer 3 · Post 3 of 14

← Previous: Retries → Next: Idempotency

Comments


About Me

DSC_7604.jpg

Hi, I am a software engineer from Bangalore, India. Love spending time on gaming and photography. This website is where I will ocassionally throw what comes to my mind. Hope it is useful or at least entertaining to you. :)

 

  • Instagram
  • Facebook
  • Twitter
  • LinkedIn
  • YouTube
  • 500px

© 2023 by Going Places. Proudly created with Wix.com

bottom of page