Skip to lesson
Exit
Deep Dive - Webhooks, Events & Reliability1 / 2

2 min lesson

Retries, backoff & DLQs

Give a plain answer to "Why add jitter on top of exponential backoff? Isn't growing the delay enough?" Then ground it in one lesson detail.

Step 1 of 2

At-least-once delivery is a promise you keep with a retry loop. The whole craft is retrying enough to ride out a blip without turning a downstream hiccup into a self-inflicted outage.

The naive version - retry immediately, forever - is how you take down a recovering service. Ten thousand clients all retry at the same instant the endpoint comes back and you knock it over again. That's a thundering herd and the fix is two ideas working together.

  1. 1Exponential backoff. Wait longer after each failure: 1s, 2s, 4s, 8s, 16s. Spacing retries out gives a struggling endpoint room to breathe instead of a flood.
  2. 2Jitter. Multiply each computed delay by a random factor (commonly 0–1, i.e. delay * random()). This smears retries across time so synchronized clients stop hammering in lockstep.
exponential backoff with full jitter
base = 1.0           # seconds
cap  = 300.0         # max 5 min between attempts

def delay(attempt):
    # exponential growth, then full jitter
    expo = min(cap, base * (2 ** attempt))
    return random.uniform(0, expo)

# attempt 0 -> up to 1s, attempt 3 -> up to 8s, attempt 7 -> up to ~128s
Jitter is the part people forget

Plain exponential backoff still synchronizes: every client that failed at the same moment retries at the same moment, just later. Jitter is what actually breaks the lockstep. "Full jitter" (uniform between 0 and the computed delay) is the AWS-blessed default and is the right thing to name in an interview.