Concept · Reliability
Circuit breakers
Stop calling a dependency that keeps failing, and probe it before trusting it again.
When a dependency is down, every call to it waits for a timeout and then fails. Callers waste time and resources, and the dependency is hammered while it's trying to recover. A circuit breaker wraps calls to a dependency and stops making them once failure is clearly the norm.
Three states
- Closed (normal): calls pass through. The breaker tracks outcomes over a sliding window — for example the last 10 seconds or the last 100 calls.
- Open: when the failure rate crosses a threshold (say 50% of at least 20 calls), the breaker opens. Calls fail immediately, without touching the dependency, for a cool-down period (say 30 seconds).
- Half-open: after the cool-down, a small number of trial calls are let through. If they succeed, the breaker closes; if they fail, it opens again for another cool-down.
closed ──(failure rate > threshold)──► open ──(cool-down elapsed)──► half-open
▲ │
└───────────────(trial calls succeed)───────────────────────────────┤
open ◄──(trial call fails)────────────┘Settings that matter
- Minimum volume before tripping, so two failures out of three calls at 3 a.m. don't open it.
- What counts as failure: timeouts and 5xx yes; 4xx usually no — a client error doesn't mean the dependency is unhealthy.
- Scope: one breaker per dependency (or per endpoint or host), so one bad endpoint doesn't block healthy ones.
Always pair with a fallback
An open breaker should lead to a useful response: cached data, a default value, a reduced page, or a clear "temporarily unavailable" for that one feature (graceful degradation).
Where to get one
Libraries such as sony/gobreaker (Go), Resilience4j (Java) and Polly (.NET), or a service mesh: Envoy's outlier detection ejects failing hosts from a load-balancing pool, which is the same idea per host. Combine with timeouts, retries and bulkheads.