Course contentsShow
← Node.js
Lesson 1427 of 1,98013. Error Handling and Resilient SystemsFree lesson

Circuit Breaking for External API Calls

You will prevent cascading failures by tripping a circuit breaker when external service latency or error rates exceed thresholds.

In this lesson, you will learn how to prevent cascading failures by tripping a circuit breaker when your external API calls exceed acceptable latency or error thresholds.

The Problem: Cascading Failures

When your Node.js application relies on a third-party service, a slowdown or outage in that service can be catastrophic. If you continue sending requests to a failing service, your event loop can become clogged with pending promises. This consumes memory and prevents your app from serving other traffic, effectively turning a partial failure into a complete system crash.

The Solution: The Circuit Breaker

A Circuit Breaker acts as an intelligent proxy between your application and the external dependency. It exists in one of three states:

  1. Closed: Requests flow through normally. The breaker monitors the error rate.
  2. Open: The external service is deemed "unhealthy." The breaker immediately rejects all requests to the service without even trying to call it, allowing the remote service time to recover.
  3. Half-Open: After a cooldown period, the breaker allows a single "test" request through. If it succeeds, the circuit closes; if it fails, it returns to the Open state.

Implementation Logic

You don't need a complex library to understand the pattern. You simply wrap your API call logic in a state-checker:

let state = 'CLOSED';
let failureCount = 0;
const THRESHOLD = 5;

async function callExternalService(params) {
  if (state === 'OPEN') {
    throw new Error('Circuit is open: External service unavailable');
  }

  try {
    const response = await fetch('https://api.example.com/data', { signal: AbortSignal.timeout(2000) });
    failureCount = 0; // Reset on success
    return response.json();
  } catch (err) {
    failureCount++;
    if (failureCount >= THRESHOLD) {
      state = 'OPEN';
      // Trigger a timer to transition back to HALF-OPEN after 30s
      setTimeout(() => state = 'HALF-OPEN', 30000);
    }
    throw err;
  }
}

By failing fast, you stop wasting resources on a downstream system that is already struggling. This protects your own process, maintains your system's overall stability, and provides a clear mechanism to fail gracefully rather than hanging indefinitely.

Key Takeaway: A Circuit Breaker protects your application from the "slow death" of waiting for failing dependencies by proactively blocking requests once a threshold of failure is met.