In this lesson, you will learn how to implement a finite state machine to manage the three critical states of a Circuit Breaker, protecting your Node.js application from cascading failures.
The Circuit Breaker Pattern
When an external dependency (like a microservice or database) begins to fail, repeatedly attempting requests consumes memory, file descriptors, and CPU cycles—eventually crashing your own service. A Circuit Breaker acts as an intelligent safety switch that transitions between three distinct states to manage these failures:
1. Closed (Operational)
In the Closed state, your application executes requests normally. A local counter tracks failures. If the failure rate crosses a pre-defined threshold (e.g., 5 failures in 30 seconds), the circuit "trips" and moves to the Open state.
2. Open (Fail-Fast)
In the Open state, the breaker immediately rejects all outgoing requests with an error or a fallback response without even attempting the network call. This gives the failing downstream service space to recover.
3. Half-Open (Probing)
After a timeout period, the breaker enters the Half-Open state. Here, it allows a single "trial" request to reach the dependency. If this request succeeds, the circuit assumes the service is healthy and moves back to Closed. If it fails, it returns to Open, resetting the recovery timer.
Implementation Logic
You can model this using a simple class structure. Here is the logic for managing state transitions:
class CircuitBreaker {
constructor() {
this.state = 'CLOSED'; // Default state
this.failures = 0;
this.threshold = 5;
}
async execute(requestFn) {
if (this.state === 'OPEN') {
throw new Error("Circuit is OPEN: Request blocked.");
}
try {
const response = await requestFn();
this.reset();
return response;
} catch (err) {
this.failures++;
if (this.failures >= this.threshold) {
this.state = 'OPEN';
setTimeout(() => (this.state = 'HALF-OPEN'), 10000); // 10s cooldown
}
throw err;
}
}
reset() {
this.failures = 0;
this.state = 'CLOSED';
}
}
By preventing your code from hammering a struggling dependency, you ensure your Node.js event loop remains responsive and your system stays stable during partial outages.
Key Takeaway: A Circuit Breaker protects your system by transitioning from Closed to Open when errors spike, and using the Half-Open state to safely test for recovery without overwhelming the dependency.