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.

TipAdvanced3 min read

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.

// 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
  }
}];
```text
After the API call, update the circuit breaker state:

```javascript
// 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
```text
```yaml
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
```text
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](../testing-and-debugging/01-use-pin-data-to-freeze-node-output.md) | [Break Large Workflows into Sub-Workflows](../workflow-architecture/01-break-large-workflows-into-sub-workflows.md)

Want this running in your stack?

I build production n8n and Cloudflare automation for teams — the same engineering behind HarperFlow. Fixed-price, escrow-protected, US-based.