1.Why circuit breakers exist: stop hammering a failing dependency
A remote call can fail outright or hang until a timeout is reached — either way, every caller that keeps trying it wastes resources (threads, connections, time) on a call that is unlikely to succeed. A circuit breaker wraps a call to a dependency and, after enough recent failures, stops attempting the call at all for a while — failing fast locally instead of repeatedly waiting on a call that keeps failing. This protects the caller from wasting its own resources, and protects the struggling dependency from a continuous stream of load that makes recovery harder, not easier.
Key features
- Without a circuit breaker, every caller of a failing dependency keeps trying, each attempt tying up a thread, connection or other resource until its own timeout fires — under load, this can exhaust the caller's own capacity purely from waiting on a dependency that was never going to succeed
- A circuit breaker tracks recent call outcomes (success/failure) for a specific dependency and, once failures cross a threshold, "trips" and stops attempting real calls for a cooldown period
- Failing fast (an immediate local error when the breaker is tripped) is dramatically cheaper than failing slow (waiting out a full timeout on every attempt) — the caller finds out sooner and can react (fallback, queue, surface an error) instead of blocking
- A circuit breaker protects in two directions at once: it protects the caller from wasting resources on a call unlikely to succeed, and it protects the struggling dependency from continued load that can make its own recovery slower or impossible
- Circuit breakers are typically scoped per dependency (or per specific downstream call), not globally — one failing dependency tripping its own breaker should not affect calls to a healthy, unrelated dependency
With vs without a circuit breaker, same failing dependency
- Without a breaker
- Full timeout paid on every single attempt
- Continuous load on the failing dependency
- A thread/connection held per in-flight call
- With a breaker (tripped)
- Immediate failure — no real call attempted
- Zero load while the breaker is open
- Caller resources freed immediately
Command
if breaker.is_tripped(dependency):
return fail_fast() # no real call attempted
else:
result = call(dependency)
breaker.record(result) # feeds the trip decision
return resultA circuit breaker stops a caller from repeatedly attempting a call to a dependency that recent evidence shows is failing — failing fast instead of failing slow, which protects both the caller's own resources and gives the struggling dependency room to actually recover.