System Design ยท Lesson 3

Circuit Breaker Pattern

A circuit breaker stops repeatedly calling an unhealthy dependency, giving it time to recover and protecting your own service from cascading failure.

The three states

Closed: calls flow normally while failures are measured. Open: calls fail fast once a threshold is crossed. Half-open: after a cooldown, a small number of trial requests are allowed. Successful trials close the breaker; failures open it again.

Why it matters

Without a breaker, an overloaded downstream service may respond slowly rather than immediately failing. Your application threads, sockets or worker capacity then wait on those calls. Traffic piles up, latency spreads through the dependency graph and healthy services can become unavailable too.

Circuit breakers need timeouts

A breaker is not a replacement for a request timeout. Every network call should have a bounded timeout appropriate to the operation. Otherwise a request can remain stuck before the breaker even receives a failure signal.

Be careful with retries

Retries can help transient failures, but uncontrolled retries multiply load on a struggling dependency. Use a small retry budget, exponential backoff and jitter, and avoid retrying operations that are not idempotent unless you have an idempotency mechanism.

Fallbacks

A fallback may return cached data, a reduced response, a queued operation or a clear temporary-unavailable error. Do not invent misleading data merely to avoid showing an error. The fallback should preserve product correctness.

Choosing thresholds

Thresholds can use consecutive failures, an error percentage over a rolling window or latency signals. Tune them using production telemetry. A threshold that is too sensitive creates unnecessary outages; one that is too tolerant does not prevent cascading failure.

Related patterns: timeouts, bulkheads, backpressure and load shedding often work alongside circuit breakers.