Skip to content

Circuit Breaker

The circuit breaker pattern prevents your application from repeatedly calling a failing service, giving it time to recover.

How It Works

  ┌─────────┐   failure threshold   ┌────────┐
  │ CLOSED  │ ─────────────────────► │  OPEN  │
  │ (normal)│                        │ (fail  │
  └────┬────┘ ◄───── success ─────── │  fast) │
       │                             └───┬────┘
       │                                 │
       │          resetTimeout           │
       │                                 ▼
       │                           ┌───────────┐
       └────── success ◄────────── │ HALF-OPEN │
                                   │  (probe)  │
               failure ──────────► └───────────┘
                  │                      │
                  └──► back to OPEN ◄────┘
  • Closed — Requests flow normally. Consecutive failures are counted.
  • Open — All requests immediately fail with CircuitOpenError. No network calls.
  • Half-Open — After resetTimeout, a limited number of probe requests are allowed. If they succeed, the circuit closes. If they fail, it re-opens.

Usage

typescript
import { CircuitBreaker, CircuitOpenError, fetchWithRetry } from 'fetch-smartly';

const breaker = new CircuitBreaker({
  enabled: true,
  failureThreshold: 5,    // Open after 5 consecutive failures
  resetTimeout: 30000,     // Try half-open after 30 seconds
  halfOpenMaxAttempts: 1,  // Allow 1 probe request
});

async function resilientFetch(url: string) {
  try {
    breaker.allowRequest(url, 'GET');
    const res = await fetchWithRetry({ url, retry: { maxRetries: 2 } });
    breaker.onSuccess();
    return res;
  } catch (error) {
    if (error instanceof CircuitOpenError) {
      console.log('Circuit is open, failing fast until', new Date(error.resetAt));
      throw error;
    }
    breaker.onFailure();
    throw error;
  }
}

Configuration

OptionDefaultDescription
enabledfalseWhether the circuit breaker is active
failureThreshold5Consecutive failures before opening
resetTimeout30000Ms before transitioning to half-open
halfOpenMaxAttempts1Probe requests allowed in half-open

Manual Reset

typescript
breaker.reset(); // Force close the circuit

Released under the MIT License.