Pattern · seen in 3 breakdowns across 3 companies
Circuit Breaker
A circuit breaker watches the calls to a dependency and, once too many fail, stops sending calls and fails them instantly for a while, so a down dependency can't tie up the whole system.
The mechanism
The pattern at its core: a stream of calls to a dependency that goes down for a while, and a breaker that steps in so those calls fail instantly instead of each waiting out the full timeout.
Send calls through an outage with timeouts only, then with a breaker - watch the wasted waiting time collapse.
Definition
A circuit breaker wraps the calls your service makes to something it depends on - a database, a payment provider, another service - and monitors those calls. It has three states:
- closed - the normal, healthy state; calls flow straight through (similar to a closed electrical circuit)
- open - state reached after too many recent failures; calls fail instantly, without even trying the dependency
- half-open - state reached after a short cooling-off wait period; one test call is let through to see if the dependency is back
It starts in closed state and switches to open state when failures pile up. After a short cooling-off wait period, it switches to half-open state. From that state, a successful test call closes it again; a failed one opens it back up for another wait.
Why not just rely on a timeout? Because a timeout is not free. It caps how long one call waits, but while the dependency is down, every new call still waits out the full timeout before giving up - tying up threads, connections, and queue slots at the worst possible moment. An outage usually stays down for a while, rather than clearing on its own within seconds. So instead of every call waiting out the full timeout for the whole outage, the breaker makes them fail right away. Pulling traffic away also gives the struggling dependency room to recover. Failing instantly makes room for a planned fallback - a cached value, a simpler path, a clear error message - but that fallback is work your application has to do; the breaker only creates the opening.
The main design decision is what exactly each breaker protects. Make its scope too broad and one small part failing trips the breaker for calls that would have worked fine. Make it too narrow and you end up with a breaker for everything, each one slower to notice trouble and each needing its own tuning. Nearly every ecosystem ships a circuit-breaker library, so writing the code is rarely the hard part. The common problem is a breaker added in a hurry: its trip thresholds get set once and never looked at again, and no one has decided what should actually happen when it trips.
When it applies
Tradeoffs
The same move, 3 ways
Every row is a production system that bet on this pattern — the note says how, in that system's own terms.
Problems this pattern answers
The walls where its breakdowns live — each opens the cross-company comparison.