Design Patterns Circuit Breaker
The Circuit Breaker pattern stops an application from repeatedly calling a service that keeps failing. After enough failures, the breaker opens and rejects calls immediately. Time passes, a test call checks recovery, and normal traffic resumes when the service heals.
The Real-World Analogy
An electrical breaker in a home panel trips when too much current flows. The trip protects wiring from damage. After the problem gets fixed, someone resets the breaker and power returns. Software breakers protect systems from a similar overload of failing requests.
Problem Without a Breaker
Checkout ──▶ Payment Service (down, each call waits 30 seconds) 100 users × 30 seconds of waiting = threads pile up Checkout runs out of threads and crashes too One broken service drags the whole system down.
Solution With a Breaker
Checkout ──▶ ┌─────────────────┐ ──▶ Payment Service
│ Circuit Breaker │
└─────────────────┘
Failures pile up → breaker opens → Checkout gets an instant answer
("Payment is busy, try again soon") instead of a long wait.
The Three States
failures reach limit
┌────────┐ ───────────────────────▶ ┌────────┐
│ CLOSED │ │ OPEN │
│ calls │ │ calls │
│ pass │ ◀─────────┐ │ blocked│
└────────┘ │ └───┬────┘
▲ │ test call │ wait time ends
│ success │ succeeds ▼
│ ┌──┴───────────┐
└─────────── │ HALF-OPEN │
│ one test call│ ── test call fails ──▶ back to OPEN
└──────────────┘
Closed
Calls flow normally. The breaker counts failures.
Open
Calls fail instantly without reaching the service. A timer runs.
Half-Open
The breaker allows a small number of test calls. Success closes the breaker, and failure reopens it.
Code Example
class CircuitBreaker {
private String state = "CLOSED";
private int failures = 0;
private int limit = 3;
private long openedAt = 0;
private long waitMillis = 10000;
Response call(Service service, Request request) {
if (state.equals("OPEN")) {
if (now() - openedAt > waitMillis) {
state = "HALF_OPEN"; // try again
} else {
return Response.fallback("Service busy, try later");
}
}
try {
Response r = service.send(request);
onSuccess();
return r;
} catch (Exception e) {
onFailure();
return Response.fallback("Service busy, try later");
}
}
private void onSuccess() {
failures = 0;
state = "CLOSED";
}
private void onFailure() {
failures = failures + 1;
if (failures >= limit || state.equals("HALF_OPEN")) {
state = "OPEN";
openedAt = now();
}
}
}Fallback Strategies
| Strategy | Example |
|---|---|
| Cached data | Show the last known product price |
| Default value | Display an empty recommendation list |
| Friendly message | "Reviews are loading slowly, check back soon" |
| Alternative service | Route to a backup provider |
Tuning the Breaker
- Failure limit: too low trips on harmless blips, and too high reacts late.
- Open duration: short waits retry too early, and long waits delay recovery.
- Timeout per call: always set one, since waiting forever defeats the purpose.
Related Patterns
State describes the three breaker modes cleanly. Proxy often wraps the remote call. Null Object supplies safe fallback answers. API Gateways commonly embed breakers for every service they reach.
Advantages and Disadvantages
| Advantages | Disadvantages |
|---|---|
| Stops cascading failures | Needs careful tuning |
| Fast responses during outages | Fallback design takes thought |
| Gives failing services room to recover | Adds monitoring needs |
Step-by-Step Walkthrough
Walk through a failing service. Three calls fail in a row, and onFailure() pushes the failure count to the limit. The breaker flips to OPEN and records the time. Calls during the next ten seconds return the fallback message immediately.
After the wait ends, the next call moves the breaker to HALF_OPEN and reaches the service. A success resets the counter and closes the breaker. Failure reopens it and restarts the timer.
Monitoring the Breaker
- Record every state change with a timestamp.
- Track failure rates per service on a dashboard.
- Alert the team when a breaker stays open for long periods.
Common Mistakes
- Counting expected errors, such as "not found," as failures.
- Skipping a fallback, which leaves users with raw error pages.
- Sharing one breaker between unrelated services, which punishes healthy ones.
Plain-Words Summary
Resilience stories often begin with a small outage that spreads. A slow payment service holds threads, the web server runs out of capacity, and the whole site goes down. Failing fast, a circuit breaker cuts that chain and giving the struggling service time to recover. Adding one around every remote call is a habit worth building early in any project.
Key Takeaways
- A circuit breaker blocks calls to a failing service for a short time.
- The three states are closed, open, and half-open.
- Fallbacks keep users informed during outages.
- Tune limits and timers against real traffic.
