What is the Circuit Breaker Pattern?
Learn the circuit breaker pattern: closed, open and half-open states, why it fails fast, and how it protects distributed systems.
Expected Interview Answer
The circuit breaker pattern wraps a call to a remote dependency with a state machine that stops sending requests to a service once it detects repeated failures, protecting the caller from wasting resources on calls that are very likely to fail.
A circuit breaker sits in three states: closed (requests flow normally while failures are counted), open (once a failure threshold is crossed, requests are rejected immediately without hitting the network), and half-open (after a cooldown, a small number of trial requests are let through to see if the dependency has recovered). If trial requests succeed the breaker closes again; if they fail it reopens and resets the cooldown. This prevents a struggling downstream service from being overwhelmed further and stops the caller from tying up threads, connection pools, and latency budgets on calls doomed to time out. Libraries like Hystrix, resilience4j, and Polly implement this pattern, and it is often paired with timeouts, retries with backoff, and fallbacks.
- Fails fast instead of waiting out a timeout on every doomed request
- Protects a struggling downstream dependency from further overload
- Frees up caller threads and connection pools that would otherwise be blocked
- Automatically probes for recovery and closes without manual intervention
AI Mentor Explanation
A circuit breaker is like a captain who stops throwing the ball to a bowler who has just been hit for four boundaries in a row, switching them out of the attack instead of persisting with an over that is clearly going badly. The captain periodically brings that bowler back for a single trial over to see if their rhythm has returned. If the trial over goes well, they stay in the attack; if it goes badly again, they are pulled straight back out. That fast, automatic switch away from a failing resource is exactly what a circuit breaker does for a struggling service.
Step-by-Step Explanation
Step 1
Closed state monitors calls
Requests flow through normally while the breaker counts recent successes and failures.
Step 2
Threshold trips the breaker open
Once failures cross a configured threshold within a window, the breaker opens and rejects calls immediately without hitting the network.
Step 3
Cooldown then half-open trial
After a timeout, the breaker allows a small number of trial requests through in the half-open state.
Step 4
Close or reopen based on trial result
Successful trials close the breaker and resume normal traffic; failed trials reopen it and reset the cooldown.
What Interviewer Expects
- Names the three states: closed, open, half-open
- Explains why failing fast is better than waiting out timeouts on every call
- Mentions real libraries: resilience4j, Hystrix, Polly
- Connects circuit breakers to timeouts, retries and fallbacks as complementary patterns
Common Mistakes
- Confusing a circuit breaker with a simple retry loop
- Forgetting the half-open trial phase and how the breaker re-closes
- Not mentioning that it protects the caller’s own resources, not just the downstream service
- Treating the threshold and cooldown as fixed values rather than tunable configuration
Best Answer (HR Friendly)
“A circuit breaker is a safety mechanism that stops a service from repeatedly calling a dependency that keeps failing. Once too many failures happen in a row, it “trips” and blocks further calls for a while, then automatically tests the dependency again later to see if it has recovered before letting traffic flow normally again.”
Code Example
class CircuitBreaker {
constructor(fn, { failureThreshold = 5, cooldownMs = 30000 } = {}) {
this.fn = fn
this.failureThreshold = failureThreshold
this.cooldownMs = cooldownMs
this.state = "closed"
this.failureCount = 0
this.openedAt = null
}
async call(...args) {
if (this.state === "open") {
if (Date.now() - this.openedAt < this.cooldownMs) {
throw new Error("circuit open: failing fast")
}
this.state = "half-open"
}
try {
const result = await this.fn(...args)
this.failureCount = 0
this.state = "closed"
return result
} catch (err) {
this.failureCount += 1
if (this.state === "half-open" || this.failureCount >= this.failureThreshold) {
this.state = "open"
this.openedAt = Date.now()
}
throw err
}
}
}Follow-up Questions
- How is a circuit breaker different from a simple retry with backoff?
- What should a caller do when a circuit breaker is open — fail, queue, or fall back?
- How do you choose the failure threshold and cooldown period for a breaker?
- How would you monitor and alert on circuit breakers tripping in production?
MCQ Practice
1. What are the three states of a circuit breaker?
A circuit breaker transitions between closed (normal), open (failing fast), and half-open (trial recovery).
2. Why does a circuit breaker fail fast instead of letting every request time out?
Failing fast frees threads and connections and reduces pressure on an already struggling downstream service.
3. What happens during the half-open state of a circuit breaker?
Half-open lets a limited number of trial calls through to decide whether to close or reopen the breaker.
Flash Cards
What is a circuit breaker? — A pattern that stops calls to a repeatedly failing dependency and fails fast instead of waiting on timeouts.
Three circuit breaker states? — Closed (normal), open (failing fast), half-open (trial recovery).
Why fail fast? — To free caller resources and reduce load on a struggling downstream service.
Popular circuit breaker libraries? — resilience4j, Hystrix (legacy), Polly.