Circuit Breaker
Resilience pattern that protects applications from cascading failures by automatically interrupting calls to failing services.
Updated on January 9, 2026
Circuit Breaker is an architectural pattern inspired by electrical circuit breakers, designed to enhance resilience in distributed systems. It monitors calls to external services and automatically interrupts requests when a failure threshold is reached, allowing the system to stabilize and preventing failure propagation throughout the architecture.
Fundamentals
- Three distinct states: Closed (normal operations), Open (blocking calls), Half-Open (recovery testing)
- Continuous monitoring of failure rates and latencies to detect anomalies
- Timeout and fallback mechanisms to gracefully handle failures
- Automatic recovery with progressive testing phase before full restoration
Benefits
- Prevention of cascading failures in microservices architectures
- Reduced response times by avoiding calls to unavailable services
- Protection of system resources (threads, connections) against exhaustion
- Improved user experience with fast responses even during outages
- Facilitated diagnostics with detailed metrics on failures and patterns
- Enable automatic recovery without manual intervention
Practical Example
Here's a TypeScript implementation of a Circuit Breaker to protect external API calls:
enum CircuitState {
CLOSED = 'CLOSED',
OPEN = 'OPEN',
HALF_OPEN = 'HALF_OPEN'
}
interface CircuitBreakerConfig {
failureThreshold: number; // Failures before opening
successThreshold: number; // Successes required to close
timeout: number; // Time before recovery test (ms)
monitoringPeriod: number; // Monitoring window (ms)
}
class CircuitBreaker {
private state: CircuitState = CircuitState.CLOSED;
private failureCount = 0;
private successCount = 0;
private lastFailureTime?: number;
private nextAttempt?: number;
constructor(private config: CircuitBreakerConfig) {}
async execute<T>(operation: () => Promise<T>): Promise<T> {
if (this.state === CircuitState.OPEN) {
if (Date.now() < this.nextAttempt!) {
throw new Error('Circuit breaker is OPEN');
}
this.state = CircuitState.HALF_OPEN;
this.successCount = 0;
}
try {
const result = await operation();
this.onSuccess();
return result;
} catch (error) {
this.onFailure();
throw error;
}
}
private onSuccess(): void {
this.failureCount = 0;
if (this.state === CircuitState.HALF_OPEN) {
this.successCount++;
if (this.successCount >= this.config.successThreshold) {
this.state = CircuitState.CLOSED;
this.successCount = 0;
}
}
}
private onFailure(): void {
this.failureCount++;
this.lastFailureTime = Date.now();
if (this.failureCount >= this.config.failureThreshold) {
this.state = CircuitState.OPEN;
this.nextAttempt = Date.now() + this.config.timeout;
}
}
getState(): CircuitState {
return this.state;
}
}
// Usage with payment service
const paymentCircuit = new CircuitBreaker({
failureThreshold: 5,
successThreshold: 2,
timeout: 60000,
monitoringPeriod: 10000
});
async function processPayment(amount: number) {
try {
return await paymentCircuit.execute(async () => {
const response = await fetch('https://api.payment.com/charge', {
method: 'POST',
body: JSON.stringify({ amount })
});
if (!response.ok) throw new Error('Payment failed');
return response.json();
});
} catch (error) {
// Fallback: log and return default response
console.error('Payment service unavailable:', error);
return { status: 'pending', message: 'Retry later' };
}
}Implementation
- Identify critical integration points requiring protection (external APIs, databases, third-party services)
- Define appropriate thresholds based on SLAs and observed traffic patterns
- Implement the pattern with proven libraries (Resilience4j, Polly, Opossum) or custom solution
- Configure fallback strategies adapted to business context (cache, default response, graceful degradation)
- Set up comprehensive observability with metrics on states, transitions, and failure rates
- Test failure and recovery scenarios in staging environment
- Adjust parameters in production based on actual performance data
Pro Tip
Combine Circuit Breaker with Retry and Timeout patterns for a comprehensive resilience strategy. Use Half-Open state with limited test requests to avoid overwhelming a recovering service. Centralize circuit breaker configuration in a dashboard for easier monitoring and real-time adjustment.
Related Tools
- Resilience4j - lightweight Java library with Circuit Breaker, Retry, Rate Limiter support
- Polly - .NET framework for resilience and transient error handling
- Hystrix - Netflix library (in maintenance) pioneer of the pattern, historical reference
- Opossum - simple and performant Node.js Circuit Breaker implementation
- Istio/Envoy - integrated circuit breakers at service mesh level
- AWS App Mesh - native circuit breaker management in cloud infrastructure
Adopting the Circuit Breaker pattern transforms the robustness of distributed architectures by converting inevitable failures into controlled and predictable behaviors. By proactively protecting against error cascades, it ensures high availability and consistent user experience, even under the most challenging conditions. This defensive approach becomes indispensable when your system depends on external or interconnected services.
