# 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.

- kind: category
- category: design-patterns
- canonical: https://aipatterns.dev/design-patterns/resilience
- inspired-by: https://learn.microsoft.com/en-us/azure/architecture/patterns

## 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](https://aipatterns.dev/design-patterns/timeout.md): 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](https://aipatterns.dev/design-patterns/circuit-breaker.md): count consecutive failures, refuse to call a dependency that just failed repeatedly, and let a probe test recovery before resuming.
- [Retry](https://aipatterns.dev/design-patterns/retry.md): re-attempt only retryable, repeatable operations a bounded number of times, honouring the server's `Retry-After`, and surface the last error.
- [Exponential Backoff](https://aipatterns.dev/design-patterns/exponential-backoff.md): the spacing policy for repeats - double the wait each attempt, cap it, and jitter so concurrent callers do not retry in lockstep.
- [Fallback](https://aipatterns.dev/design-patterns/fallback.md): return a pre-decided lesser answer - stale cache, static default, partial result - so the caller's journey continues, marked as degraded.
- [Rate Limiting](https://aipatterns.dev/design-patterns/rate-limiting.md): give each client a refillable budget of calls; refuse with `429` and a `Retry-After` when it runs out.

## How to choose

- **A remote call has no explicit deadline:** [Timeout](https://aipatterns.dev/design-patterns/timeout.md). 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](https://aipatterns.dev/design-patterns/retry.md) with [Exponential Backoff](https://aipatterns.dev/design-patterns/exponential-backoff.md) spacing.
- **Calls keep failing in bursts and callers pile up waiting or retrying:** [Circuit Breaker](https://aipatterns.dev/design-patterns/circuit-breaker.md). It needs timeouts to classify hangs as failures first.
- **The user journey must continue without the data:** [Fallback](https://aipatterns.dev/design-patterns/fallback.md) - after retries are exhausted, or immediately while a breaker is open.
- **One client's burst starves the others:** [Rate Limiting](https://aipatterns.dev/design-patterns/rate-limiting.md). 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](https://aipatterns.dev/design-patterns/command.md) 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.
