API / Microservices Design Patterns Interview Questions
What is the Retry pattern with exponential backoff and jitter, and when should you NOT retry?
The Retry pattern automatically re-attempts a failed operation a limited number of times before declaring it a final failure. On its own, retrying immediately (fixed delay or no delay) can overwhelm a struggling downstream service. Exponential backoff solves this by increasing the delay between retries exponentially:
delay(attempt) = base * 2^attempt // attempt 1: 1s, attempt 2: 2s, attempt 3: 4s, attempt 4: 8s ...
Adding jitter (random noise) to the backoff prevents the thundering herd problem — when many clients retry simultaneously after a shared outage, they all backoff to the same windows and hammer the recovering service in synchronized bursts. With jitter, each client's retry time is randomised within the backoff window:
// Full jitter (recommended by AWS) delay(attempt) = random(0, base * 2^attempt) // Decorrelated jitter delay(n) = min(cap, random(base, delay(n-1) * 3))
When NOT to retry:
- Non-idempotent operations — a
POST /chargesthat creates a charge must not be retried without idempotency keys; retrying will create duplicate charges. - 4xx client errors — HTTP 400 (Bad Request), 401 (Unauthorised), 403 (Forbidden), 404 (Not Found). These indicate problems with the request itself; retrying will produce the same failure.
- 429 Too Many Requests — only retry after respecting the
Retry-Afterheader; retrying aggressively makes the rate-limit situation worse. - Circuit is Open — if the circuit breaker has already tripped, adding retries amplifies the load on an already-failing service.
- Deadlines exceeded — if the caller's overall timeout budget is already exhausted, retrying only prolongs the client's wait without any chance of success within budget.
More Related questions...