CircuitBreakerPlugin
Prevents a failing upstream from being hammered during outages. Trips open after N failures, fast-fails all subsequent requests, and allows configurable test probes before closing again.
Install
import { createCircuitBreaker } from 'axios-retryer/plugins/CircuitBreakerPlugin'; Basic usage
import { createRetryer } from 'axios-retryer';
import { createCircuitBreaker } from 'axios-retryer/plugins/CircuitBreakerPlugin';
const retryer = createRetryer().use(
createCircuitBreaker({
failureThreshold: 5, // Consecutive failures before tripping open
openTimeout: 30_000, // ms to wait before testing (half-open)
halfOpenMax: 2, // Probe requests allowed in half-open state
}),
); All options
createCircuitBreaker({
failureThreshold: 5, // Failures before circuit trips (default: 5)
openTimeout: 30_000, // ms in OPEN state before going HALF-OPEN (default: 30000)
halfOpenMax: 2, // Test requests in HALF-OPEN before deciding (default: 1)
successThreshold: 2, // Successes in HALF-OPEN to close again (default: 1)
useSlidingWindow: true, // Count failures within a time window (default: false)
slidingWindowSize: 60_000, // Window size in ms (default: 60000)
excludeUrls: [ // URL patterns that bypass the breaker
/\/healthcheck/,
'/api/status',
],
}) Circuit states
| State | Behaviour | Transition |
|---|---|---|
| CLOSED | Normal operation — requests flow through | → OPEN when failures ≥ failureThreshold |
| OPEN | All requests fail fast with CircuitBreakerStateError | → HALF-OPEN after openTimeout |
| HALF-OPEN | Up to halfOpenMax probe requests allowed | → CLOSED after successThreshold successes; → OPEN on any failure |
Inspecting breaker state
import { createRetryer } from 'axios-retryer';
import { createCircuitBreaker } from 'axios-retryer/plugins/CircuitBreakerPlugin';
const breaker = createCircuitBreaker({ failureThreshold: 5, openTimeout: 30_000 });
const retryer = createRetryer().use(breaker);
// Current state
console.log(breaker.getState()); // 'CLOSED' | 'OPEN' | 'HALF_OPEN'
// Per-scope and global metrics
const metrics = breaker.getMetrics();
console.log(metrics.failureCount);
console.log(metrics.successCount);
// Adaptive-timeout telemetry (when enabled)
console.log(breaker.getAdaptiveTimeoutMetrics());
// Operational controls
breaker.manualReset();
breaker.resetMetrics(); manualReset() closes one scope or all known scopes immediately. resetMetrics() zeros counters without changing the current circuit state, and getAdaptiveTimeoutMetrics() exposes the learned timeout percentiles when adaptive timeouts are enabled.
Handling the open circuit
import { CircuitBreakerStateError } from 'axios-retryer/plugins/CircuitBreakerPlugin';
// `retryer` = manager with CircuitBreakerPlugin (see basic usage above)
try {
await retryer.axiosInstance.get('/api/orders');
} catch (err) {
if (err instanceof CircuitBreakerStateError) {
// Don't alert — this is expected circuit-breaker behaviour
return cachedFallback ?? { orders: [] };
}
throw err; // Surface other errors normally
} Sliding window example
Count failures in a rolling 60-second window instead of a cumulative counter:
createCircuitBreaker({
failureThreshold: 10,
openTimeout: 15_000,
useSlidingWindow: true,
slidingWindowSize: 60_000, // Trip open if 10 failures occur within 60 seconds
}) Excluding URLs
Health-check and monitoring endpoints should bypass the breaker:
createCircuitBreaker({
failureThreshold: 5,
openTimeout: 30_000,
excludeUrls: [/\/health/, '/metrics', '/ping'],
}) openTimeout controls how long the circuit stays open before probing. Setting it very low means faster recovery attempts but can lead to repeated trips if the upstream is still unstable.