Tips > Building Workflows

Build Retry-with-Fallback for Critical Operations

For operations where failure is not acceptable (sending a customer notification, recording a payment, logging an audit event), the retry-with-fallback

Build retry-with-fallback for a critical operation by sending it to a primary service with its On Error setting set to continue using the error output, then routing that error branch to a backup service. If the fallback also fails, raise an alert. Unlike built-in retry-on-error, which retries the same service, this fails over to a different provider so the operation still completes.

How is retry-with-fallback different from retry-on-error?

For operations where failure is not acceptable (sending a customer notification, recording a payment, logging an audit event), the retry-with-fallback pattern tries the primary service, and if it fails after retries, routes to a backup service. This is more robust than n8n's built-in retry-on-error, which retries the same service.

How do you build retry-with-fallback in n8n?

Real-world example: Your workflow sends transactional emails via SendGrid. If SendGrid is down, it falls back to Amazon SES.

Trigger
  |
  HTTP Request - SendGrid (primary)
    On Error: Continue (using error output)
  |
  +-> Success branch: Continue workflow
  |
  +-> Error branch:
        |
        Code Node - Log Failure
        |
        HTTP Request - Amazon SES (fallback)
          On Error: Continue
        |
        +-> Success: Continue workflow
        |
        +-> Error: Slack Alert (both providers down)

Configure the primary SendGrid HTTP Request node, with retries and a timeout, and set On Error to continue using the error output:

{
  "method": "POST",
  "url": "https://api.sendgrid.com/v3/mail/send",
  "authentication": "genericCredentialType",
  "sendBody": true,
  "bodyContentType": "json",
  "jsonBody": {
    "personalizations": [
      {
        "to": [{ "email": "={{ $json.customer_email }}" }],
        "subject": "Your order #{{ $json.order_id }} has shipped"
      }
    ],
    "from": { "email": "orders@example.com" },
    "content": [
      {
        "type": "text/html",
        "value": "={{ $json.email_body_html }}"
      }
    ]
  },
  "options": {
    "timeout": 10000,
    "retry": {
      "maxRetries": 2,
      "waitBetweenRetries": 2000
    }
  }
}

On the error branch, a Code node logs the failure and reshapes the payload into the fallback provider's format (Amazon SES):

const originalInput = $('Trigger').first().json;
const sendgridError = $input.first().json;

console.log(`SendGrid failed: ${JSON.stringify(sendgridError)}`);

// Prepare the same email data in SES format
return [{
  json: {
    Destination: {
      ToAddresses: [originalInput.customer_email]
    },
    Message: {
      Subject: {
        Data: `Your order #${originalInput.order_id} has shipped`
      },
      Body: {
        Html: {
          Data: originalInput.email_body_html
        }
      }
    },
    Source: "orders@example.com",
    // Pass through original data for downstream nodes
    _original: originalInput
  }
}];

Tip: Error Output Configuration. To use the error branch, configure the node's settings: On Error -> Continue Using Error Output. This adds a second output connector (red) that receives items when the node fails, including the error details. The success output (green) receives items when the node succeeds.

When should you use retry-with-fallback?

This pattern ensures critical operations complete even during provider outages, with full visibility into which fallback path was used.

Related: Use Path Parameters in Webhook URLs for Dynamic Routing · Use Edit Fields in "Map Each" Mode for Simple Renames

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