Blog
BLOG — Guide

Error Handling and Retries: What Makes a Workflow Unbreakable

The reason a workflow that ran fine in demos falls apart the moment it hits production is almost always the same. External APIs occasionally return 500s, webhooks occasionally arrive twice, data occasionally arrives empty. You can't eliminate failure. You can only build workflows that handle it.

This post covers the four patterns you have to add the moment you move from demo to production: Retry on Fail, Error Trigger, idempotency keys, and dead letters. Just having these four in place dramatically cuts down on 3 a.m. Slack alerts and frantic log-diving.

1. Turn on retries first — the cheapest defense

For any node that makes a network call, flipping Settings → Retry On Fail alone knocks out 70–80% of transient errors. Things like HTTP 502s, timeouts, DNS failures. The default is 3 tries at 1-second intervals, but in production you'll want to mimic exponential backoff and space them out.

// HTTP Request node config example
{
  "retryOnFail": true,
  "maxTries": 4,
  "waitBetweenTries": 2000,   // 2s → 4s → 8s (manually spaced)
  "continueOnFail": false
}
Turning on Continue On Fail lets the next node run even when this one fails. It looks convenient but it's an antipattern that silently swallows failures. If you use it, always check $json.error in the next node.

2. Build a failure-only flow with Error Trigger

What happens when retries are exhausted? By default the workflow dies and leaves a trace only in the execution log. Nobody reads that. Build a separate workflow with an Error Trigger node and you can push instant notifications to Slack, email, or PagerDuty the moment things break.

  1. Create a new workflow → drop in one Error Trigger node
  2. In the failing workflow's Settings → Error Workflow, point to the one you just made
  3. Connect a Slack or Email node after the Error Trigger
  4. Include {{ $json.execution.url }} in the message so you can jump straight to the failed execution
  5. Load the failure payload into a failed_jobs table via a Postgres node
Failure-handling pipelineLIVE
ERRError TriggerROUTESeverity branchSLKSlack notifyPGfailed_jobs insert

3. Idempotency — is it safe to run twice?

Retries aren't a silver bullet. If you send a request to a payment API and the response never comes back, retrying might charge the customer twice. Same for sending emails. The key is to make the operation idempotent — same input, same result, no matter how many times it runs.

The most common pattern is attaching a unique Idempotency-Key header to each request. Stripe, Toss, Shopify, and other major payment and commerce APIs support this header as a standard.

// HTTP Request node Headers
{
  "Idempotency-Key": "{{ $json.orderId }}-{{ $now.toFormat('yyyyMMdd') }}"
}

// The server reuses the first response when the same key comes in twice

What if the payment API doesn't support the header? Plant a Postgres node at the start of the workflow with INSERT ... ON CONFLICT DO NOTHING so already-processed order IDs get silently skipped.

4. Dead letters — don't throw failed data away

If retries fail and no human sees the alert, where does that data go? Usually into the void. Create a failed_jobs table and keep the original payload, the failure timestamp, the error message, and the retry count. Once you've fixed the root cause, you can batch-reprocess.

  • payload_json — the entire original request/data
  • error_message — the first 200 chars of n8n's error output
  • node_name — which node died
  • retry_count — how many retries were attempted
  • created_at, resolved_at — occurrence and resolution timestamps
Hook the dead-letter table into a dashboard and the whole team can see which pipelines are hurting at a glance. Grafana, Metabase, doesn't matter.

What actually happens when you build this

Here's the result of applying all four patterns to one e-commerce client's Order → ERP integration. 30 days before vs. 30 days after rollout.

Overnight failure alerts
12/month → 1/month
Data loss incidents
8/month → 0/month
MTTR (mean time to recovery)
3.5 hours → 22 minutes
Duplicate payment incidents
2/quarter → 0/quarter
A trustworthy workflow isn't one that never fails. It's one where the failure is visible and reversible.SynAct.ai Consulting Team

Wrap-up

There's no such thing as a perfect workflow. But you can build a workflow where the alert lands within 30 seconds, the data doesn't disappear, and one re-run recovers everything after you patch the root cause. The four patterns above are the bare minimum. Treat them as your checklist before promoting anything to production.

This guide was verified on n8n 2.29.9 with the retry · Error Trigger · DLQ · alerting combo, exercised against real failure scenarios (HTTP 5xx, timeouts, bad credentials). Last verified: 2026-03-08.
Book a free 30-minute audit to see whether your current workflows have these four in place. We'll walk through the failure points with you and prioritize what to fix first.

Reading is fine.
Doing is better.

We'll apply what you read to your operation. Start with a free audit.

One hands-on automation piece a month

n8n patterns, AI-agent recipes, and case studies — one email a month. No sales pitches, no filler.

Unsubscribe anytime · No spam