Nitrogen
HomePostsTagsAbout
Back to Posts
ArchitectureAPIs

Building Resilient APIs with the Circuit Breaker Pattern

2026-05-112 min read

In distributed systems, failures are inevitable. The circuit breaker pattern prevents a single failing service from cascading into a system-wide outage.

How It Works

A circuit breaker monitors calls to external services and "trips" (opens) when failures exceed a threshold. It has three states:

  • Closed: Requests flow normally. Failures are counted.
  • Open: Requests are immediately rejected with a fallback response.
  • Half-Open: After a timeout, a limited number of test requests are allowed through.

Implementation

class CircuitBreaker {
  private failures = 0;
  private lastFailure = 0;
  private state: 'closed' | 'open' | 'half-open' = 'closed';

  constructor(
    private threshold: number = 5,
    private timeout: number = 30000
  ) {}

  async call<T>(fn: () => Promise<T>): Promise<T> {
    if (this.state === 'open') {
      if (Date.now() - this.lastFailure > this.timeout) {
        this.state = 'half-open';
      } else {
        throw new Error('Circuit is open');
      }
    }

    try {
      const result = await fn();
      this.onSuccess();
      return result;
    } catch (error) {
      this.onFailure();
      throw error;
    }
  }

  private onSuccess() {
    this.failures = 0;
    this.state = 'closed';
  }

  private onFailure() {
    this.failures++;
    this.lastFailure = Date.now();
    if (this.failures >= this.threshold) {
      this.state = 'open';
    }
  }
}

Best Practices

  1. Use with retry logic: Combine with exponential backoff for transient failures.
  2. Monitor circuit states: Expose metrics for alerting when circuits open.
  3. Provide meaningful fallbacks: Return cached data or degraded functionality instead of errors.