Circuit Breaker Pattern: Definition, Usage, and Example
circuit breaker pattern is a design pattern used in microservices to prevent repeated calls to a failing service by stopping requests temporarily. It acts like an electrical circuit breaker that trips to avoid damage, improving system stability and fault tolerance.How It Works
Imagine a circuit breaker in your home that stops electricity flow when there is a fault to prevent damage. Similarly, in software, the circuit breaker pattern monitors calls to a service. If the service fails repeatedly, the circuit breaker "trips" and stops further calls for a set time.
During this "open" state, the system quickly returns an error or fallback response without trying the failing service. After some time, the circuit breaker allows a few test requests to check if the service has recovered. If successful, it closes the circuit and resumes normal calls.
This mechanism prevents wasting resources on calls likely to fail and helps the system recover gracefully.
Example
This example shows a simple circuit breaker in JavaScript that stops calling a failing service after 3 failures and retries after 5 seconds.
class CircuitBreaker { constructor(failureThreshold, recoveryTime) { this.failureThreshold = failureThreshold; this.recoveryTime = recoveryTime; // milliseconds this.failureCount = 0; this.state = 'CLOSED'; this.nextAttempt = Date.now(); } async call(serviceCall) { if (this.state === 'OPEN') { if (Date.now() > this.nextAttempt) { this.state = 'HALF_OPEN'; } else { throw new Error('Circuit breaker is OPEN'); } } try { const response = await serviceCall(); this.success(); return response; } catch (error) { this.fail(); throw error; } } success() { this.failureCount = 0; this.state = 'CLOSED'; } fail() { this.failureCount++; if (this.failureCount >= this.failureThreshold) { this.state = 'OPEN'; this.nextAttempt = Date.now() + this.recoveryTime; } } } // Simulated service call that fails randomly async function unreliableService() { if (Math.random() < 0.7) { throw new Error('Service failure'); } return 'Success'; } (async () => { const breaker = new CircuitBreaker(3, 5000); for (let i = 0; i < 10; i++) { try { const result = await breaker.call(unreliableService); console.log('Call', i + 1, ':', result); } catch (e) { console.log('Call', i + 1, ':', e.message); } await new Promise(r => setTimeout(r, 1000)); } })();
When to Use
Use the circuit breaker pattern when your system depends on external services or microservices that might fail or become slow. It helps avoid cascading failures by stopping calls to a failing service and giving it time to recover.
Common real-world cases include:
- Calling a payment gateway that might be down
- Accessing a database or cache that is temporarily unreachable
- Integrating with third-party APIs with rate limits or instability
This pattern improves system resilience and user experience by failing fast and avoiding long waits.
Key Points
- The circuit breaker monitors failures and stops calls after a threshold.
- It has three states: CLOSED (normal), OPEN (stop calls), HALF-OPEN (test recovery).
- Prevents wasting resources on failing services and reduces cascading failures.
- Improves system stability and user experience.