Category
Resilience Patterns
Patterns for calls that can fail, hang or come back wrong: bound the wait, count the failures, space the repeats, and continue with a lesser answer.
What these patterns solve
A dependency that fails slowly is worse than one that fails loudly. A hung socket holds a worker, the held workers exhaust the pool, and a dead shipping API becomes a dead checkout. And once a call does fail, the caller has three honest options: try again because the failure looked transient, stop trying because the dependency is down, or continue without the answer. Without patterns the defaults are the worst ones: unbounded waits, immediate repeats, and no plan B.
These patterns convert slow failure into fast failure, bound every repeat, and decide what the caller serves instead.
Members
- Timeout: give every remote call a deadline shorter than the caller's own budget, cancel the work when it expires, and surface the timeout as a distinct error.
- Circuit Breaker: count consecutive failures, refuse to call a dependency that just failed repeatedly, and let a probe test recovery before resuming.
- Retry: re-attempt only retryable, repeatable operations a bounded number of times, honouring the server's
Retry-After, and surface the last error. - Exponential Backoff: the spacing policy for repeats - double the wait each attempt, cap it, and jitter so concurrent callers do not retry in lockstep.
- Fallback: return a pre-decided lesser answer - stale cache, static default, partial result - so the caller's journey continues, marked as degraded.
- Rate Limiting: give each client a refillable budget of calls; refuse with
429and aRetry-Afterwhen it runs out.
How to choose
- A remote call has no explicit deadline: Timeout. This is the baseline; nothing else here works without it.
- The error is transient-looking (timeouts, 429, 503) and the operation can be repeated safely: Retry with Exponential Backoff spacing.
- Calls keep failing in bursts and callers pile up waiting or retrying: Circuit Breaker. It needs timeouts to classify hangs as failures first.
- The user journey must continue without the data: Fallback - after retries are exhausted, or immediately while a breaker is open.
- One client's burst starves the others: Rate Limiting. Ration per client before the resource notices the load.
- The operation cannot be repeated safely (payments, writes without an idempotency key): none of them. Make it repeatable first (Command plus a durable queue with deduplication), or fail and let a human or workflow decide.
Prefer no pattern when
- The call is in-process and cannot hang. A function call that throws needs no deadline.
- The platform already enforces deadlines or retries end to end (gRPC deadlines, Go
context, HTTP clients with built-in retry). Configure those instead of wrapping a second layer - two retry layers multiply, not add. - The failure is permanent (validation, missing resource, business rejection). Fix the input; do not repeat it.
- The caller has no latency budget for a second attempt. Fail fast instead.
See also
- TimeoutGive every remote call a deadline shorter than the caller's own budget, cancel the work when it expires, and surface the timeout as a distinct error.
- Circuit BreakerCount consecutive failures to a dependency, refuse calls while it looks broken, and let one probe test recovery - so a dead service cannot eat its callers.
- RetryRe-attempt only retryable, repeatable operations a bounded number of times, honour Retry-After, check cancellation between attempts, and surface the last error.
- Exponential BackoffSpace repeat attempts at base times two raised to the attempt, capped, with random jitter - so retries spread out instead of arriving in a synchronized herd.
- FallbackReturn a pre-decided lesser answer when a dependency cannot - stale cache, static default, partial result - so the journey continues, marked as degraded.
- Rate LimitingGive each client a refillable budget of calls - take a token to proceed, refuse with 429 and a Retry-After when the bucket is empty - so one client's burst cannot spend everyone's capacity.
Original writing and examples. Topic coverage follows Microsoft Azure Architecture Center, which explains this topic with its own illustrations.