Docs Plugins

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

StateBehaviourTransition
CLOSEDNormal operation — requests flow through→ OPEN when failures ≥ failureThreshold
OPENAll requests fail fast with CircuitBreakerStateError→ HALF-OPEN after openTimeout
HALF-OPENUp 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 affects both detection and recovery

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.

CachingPlugin → All Plugins