Home Services Work About Blog FAQ Contact
← Back to blog

Why your n8n webhook workflow needs an idempotency check.

Every webhook-driven automation will eventually receive the same event twice — a retry, a re-save, a platform replay. Whether your workflow handles that gracefully or doubles your data is a design decision, not a fluke.

An order comes in. Your n8n webhook fires, creates the fulfillment record, sends the confirmation email, marks the job done. Then, two minutes later, the same webhook fires again.

Not a bug in your workflow. The sender retried because the original request didn't get a fast enough response — maybe your n8n execution was slow, maybe there was a brief network hiccup. Either way, now there are two fulfillment records, two confirmation emails, and a customer who's about to be confused.

This isn't an edge case. It's the expected behavior of HTTP webhook delivery. Any system that sends webhooks will retry on timeout or network error, and that retry is indistinguishable from a first delivery. The only difference is that your workflow has already run once for this event.

Why retries happen

HTTP is a request-response protocol. When a webhook sender doesn't get a successful response in time, it assumes delivery failed and tries again. Payment platforms like Stripe retry failed deliveries for hours. E-commerce platforms like Shopify retry over a span of days. Meta's webhook subscriptions can replay events when you reconnect a subscription endpoint.

n8n creates an additional timing risk here. There's a gap between the webhook trigger firing and the workflow finishing all its work. A slow execution — one that hits external APIs, reads from a database, or runs through a lot of nodes — can take several seconds. If the sender's timeout is shorter than your execution time, it retries before you've even responded to the first request.

The short version: if you run webhook-driven automations long enough, you will get duplicates. The question is whether you've built for it.

The worst automation bug is the one that processes the same event twice, creates two records, and sends two emails — all without a single node turning red.

What a typical workflow does

Most n8n workflows don't account for this. They receive the payload, process it top to bottom, and treat every execution as a fresh event. If the same order ID shows up twice in an hour, they handle it twice.

What happens downstream depends on what the workflow writes. Two rows in Airtable or Google Sheets. Two Slack messages to your operations team. Two invoices. Two charges through your payment API. Two confirmation emails with the same booking details.

None of these will raise an n8n error. Both executions succeed. This is exactly what makes it hard to catch — there's no alert, no red node, nothing. You find out when a customer replies asking why they got charged twice, or when you're reconciling your records and nothing adds up.

The check: read the ID before you act

An idempotency check gives a workflow a way to detect it's already handled a specific event, and skip the work if it has. The logic is simple: before doing anything with side effects, look up whether this event ID has been processed before. If yes, stop. If no, mark it processed and continue.

Every useful webhook payload includes a unique identifier for the event — an order ID, a payment intent ID, a form submission UUID. That's your key. The implementation can be as light or as heavy as your stack warrants.

The simplest version uses whatever database your stack already has. An Airtable table, a Baserow database, even a Google Sheet with two columns: event ID and timestamp. At the start of the workflow, do a lookup for the incoming event ID. If you find a record, exit. If you don't, write the record first, then do your actual processing.

For automations that call payment APIs, there's often a native option. Stripe, for instance, accepts an Idempotency-Key header on API requests — pass the original webhook event ID as that key and Stripe will deduplicate the charge on their end even if your n8n workflow fires twice. It's worth checking whether the APIs you're calling have an equivalent before building a custom dedup layer.

n8n's built-in Static Workflow Data ($workflow.staticData in the Code node) can hold small amounts of persistent state between executions. It's fast, requires no external database, and works well for low-volume workflows. The tradeoff: it doesn't survive a workflow republish or a self-hosted server restart, so don't rely on it as your only safeguard if continuity matters.

Get the order right: mark before you act

One detail that's easy to get backwards: write the event ID to your dedup store before doing the external work, not after.

If you process the event first — send the email, create the record, charge the card — then write to the dedup table, and the workflow errors between those two steps, you've sent the email but have no record that you did. The next retry comes in, finds no match in the dedup table, and processes it again.

The right sequence is check → mark → act. If the workflow fails between mark and act, you'll have a record saying the event was handled but no action was taken. That's recoverable — you can see the ID in your table and manually reprocess or investigate. A duplicate action, especially a charge or an outbound message, often isn't recoverable at all.

This isn't just an e-commerce problem

This came up in an n8n community thread about e-commerce automation — specifically, which workflows to build first for an online store — and the idempotency concern was the first thing I'd add to any order-processing flow. But the same issue shows up anywhere a webhook drives an action with side effects.

Lead routing automations can create duplicate contacts in a CRM. Booking confirmations can double-schedule appointments. Invoice generators can issue two invoices for one job. Slack notification workflows can send the same message twice to the same channel. In every case, the second execution is indistinguishable from the first inside n8n.

The test is pretty simple: if the action your workflow takes would be a problem if it happened twice, it needs a dedup check. Sending a summary report once a week — low stakes, obvious if it doubles. Charging a customer — you want the check.

We cover a related failure mode — workflows that run green but whose writes never actually landed in the target system — in this post on verifying that n8n actions actually complete. The two problems look similar from the outside (workflow runs clean, something's wrong) but have opposite causes.

If you're building webhook-driven automations for your business and want help designing them to handle edge cases from the start, our automation services page covers what we build and how we approach production reliability.

— Cole

Sources

Building webhook automations that need to run clean in production?

We design n8n workflows with error handling, dedup logic, and monitoring built in — not bolted on later. Happy to take a look at what you're building.

Get in Touch →