Tips > Reliability & Performance

Implement Circuit Breaker Patterns for Fragile Integrations

When an external API is down, continuing to send requests wastes resources and may get your API key throttled.

A circuit breaker stops calling an external API after several consecutive failures, so a downed integration cannot waste executions or get your key throttled. Track state (closed, open, or half-open) in a persistent store: count failures, open the circuit past the threshold, skip calls while it is open, and test recovery after a timeout before closing it again.

What is a circuit breaker in n8n?

When an external API is down, continuing to send requests wastes resources and may get your API key throttled. Implement a circuit breaker: after N consecutive failures, stop calling the API and alert your team. Periodically test if the API has recovered before re-enabling the workflow.

Real-world example: A workflow calls a third-party inventory API every 5 minutes. The API goes down for 2 hours. Without a circuit breaker, you accumulate 24 failed executions and 72 wasted retry attempts. With a circuit breaker, you detect the outage after 3 failures and stop until it recovers.

How do you implement the circuit breaker check?

// Code node: "Circuit Breaker Check"
// Runs at the start of the workflow, before any API calls

// Read circuit breaker state from a persistent store (Google Sheet or DB)
// The previous node should fetch the current state
const state = $input.first().json;

const FAILURE_THRESHOLD = 3;       // Open circuit after 3 consecutive failures
const RECOVERY_TIMEOUT_MS = 300000; // Try again after 5 minutes (300,000 ms)

const now = Date.now();
const consecutiveFailures = state.consecutive_failures || 0;
const lastFailureTime = state.last_failure_time
  ? new Date(state.last_failure_time).getTime()
  : 0;
const circuitState = state.circuit_state || 'closed'; // closed | open | half-open

if (circuitState === 'open') {
  // Check if enough time has passed to try again
  if (now - lastFailureTime > RECOVERY_TIMEOUT_MS) {
    return [{
      json: {
        action: 'proceed',
        circuitState: 'half-open',
        message: 'Circuit half-open: testing if API has recovered'
      }
    }];
  }

  // Circuit is still open -- skip the API call
  return [{
    json: {
      action: 'skip',
      circuitState: 'open',
      message: `Circuit open: ${consecutiveFailures} consecutive failures. ` +
               `Next retry in ${Math.round((RECOVERY_TIMEOUT_MS - (now - lastFailureTime)) / 1000)}s`
    }
  }];
}

// Circuit is closed or half-open -- proceed with the API call
return [{
  json: {
    action: 'proceed',
    circuitState: circuitState,
    consecutiveFailures
  }
}];

After the API call, update the circuit breaker state:

// Code node: "Update Circuit Breaker State"
// This node has two inputs: success branch and failure branch

const previousState = $('Circuit Breaker Check').first().json;
const apiResult = $input.first().json;

let newState;

if (apiResult.error) {
  // Failure -- increment counter
  const failures = (previousState.consecutiveFailures || 0) + 1;
  const isOpen = failures >= 3; // FAILURE_THRESHOLD

  newState = {
    consecutive_failures: failures,
    last_failure_time: new Date().toISOString(),
    circuit_state: isOpen ? 'open' : previousState.circuitState,
    last_updated: new Date().toISOString()
  };

  if (isOpen && previousState.circuitState !== 'open') {
    // Circuit just opened -- send alert
    newState.alert = `Circuit OPENED for inventory API after ${failures} consecutive failures`;
  }
} else {
  // Success -- reset counter
  newState = {
    consecutive_failures: 0,
    last_failure_time: null,
    circuit_state: 'closed',
    last_updated: new Date().toISOString()
  };

  if (previousState.circuitState === 'half-open') {
    newState.alert = 'Circuit CLOSED: inventory API has recovered';
  }
}

return [{ json: newState }];
// Next node: Write this state back to the persistent store

What are the circuit breaker states?

Circuit breaker state transitions:

CLOSED (normal operation):
  API call succeeds --> stay CLOSED, reset failure count
  API call fails    --> increment failure count
  Failure count >= 3 --> transition to OPEN, send alert

OPEN (API assumed down):
  Skip all API calls
  After 5 minutes   --> transition to HALF-OPEN

HALF-OPEN (testing recovery):
  API call succeeds --> transition to CLOSED, send recovery alert
  API call fails    --> transition to OPEN, reset timer

This protects your workflows from wasting resources on a down API and gives you immediate notification when an integration breaks or recovers.

Related: Use "Pin Data" to Freeze Node Output · Break Large Workflows into Sub-Workflows

Showcase builds

19 complete workflows from my own projects, each with its n8n workflow JSON to import. Showcase entries link the file at the end of the article.

See the showcase builds

Keep reading

190 entries grouped by topic, from first workflow to queue mode. Free, no signup.

Browse the encyclopedia

Need it built?

I design, build and run n8n systems for clients. Every engagement starts with a $1,500 diagnostic audit, credited toward the build.

Book an introductory call