Docs · Integrations
Using Relay in front of an n8n webhook
If you found this page from an n8n bug thread or the community forum: this is a setup guide, not a sales pitch. It uses Relay’s existing route-creation flow — nothing here is unreleased or n8n-specific under the hood. Read “What actually changes, and what doesn’t” below before you touch anything; it says plainly which parts of your problem this fixes and which parts it doesn’t.
The problem#
n8n’s own Webhook trigger node has a handful of documented, current reliability bugs. If you’re running Stripe, Shopify, WhatsApp, or any other webhook source through n8n, you’ve probably hit one of these:
- Webhooks randomly stop firing and need a manual workflow toggle to bring them back. While the listener is silently down, anything sent during that window is gone — the sender doesn’t know n8n stopped listening, and n8n never re-fires the events it missed. Reported on the n8n community forum under the title “Not Sustainable” (community.n8n.io/t/…119667).
- Activating a workflow through the REST API doesn’t always register the webhook path, so a workflow deployed programmatically (CI/CD, infrastructure-as-code) can go live with a dead webhook until someone opens the n8n UI and re-saves it (GitHub #21614 — a fix shipped in n8n 2.14.0 via PR #27161; if you’re on an older version or a different edge case of the same bug class, it may still bite).
- n8n Cloud enforces a hard 100-second Cloudflare timeout on webhook responses. A workflow that takes longer than that to finish fails with a 524, regardless of what the workflow was actually doing (n8n docs, common webhook issues).
- A separate, still-open report of a Production Webhook that always returns 200 OK with nothing actually registered behind it, on both n8n Cloud and fresh self-hosted workflows (GitHub #16339).
Two more citations for the first bug above — the community forum thread only describes the symptom; these two GitHub issues document actual instances of it, and were re-read for this page on 2026-09-17:
- GitHub #27416 is a strictly better-documented root cause for the same “workflow deactivates itself” symptom than the forum thread above. In multi-main queue-mode deployments, a transient activation failure during startup or a leader takeover makes n8n unconditionally write
active: false, activeVersionId: nullto the database — with no retry, no automatic recovery on the next leadership change (getAllActiveIds()excludes a nulled workflow permanently), and no audit trail, and the failure cascades to any parent workflow that calls the deactivated one via anexecuteWorkflownode. Reported against n8n 2.12.0, confirmed independently on 2.13.1. Re-read on 2026-09-17: closed, fixed in n8n 2.17.0 via PR #28110. If you’re not yet on 2.17.0+ and run multi-main queue mode, treat this as still live. - GitHub #11424 is the same silent-stop shape on a plain single-instance deployment: a self-hosted Slack webhook on Render (n8n 1.64.0, SQLite, regular execution mode) answered fine for days, then stopped responding to Slack’s challenge request; deleting and recreating the webhook trigger was the only fix anyone found. Re-read on 2026-09-17: closed, but n8n’s team never identified a root cause — no fix shipped, workaround only.
These bugs live inside n8n’s own webhook-handling and activation logic. Relay doesn’t patch n8n’s code and can’t reach into n8n’s internals — what it changes is what happens to your data while n8n is having one of these moments, because Relay, not n8n, is the first thing that receives the request.
What actually changes, and what doesn’t#
Putting Relay in front of your n8n workflow means: instead of Stripe/Shopify/your other webhook source posting directly to n8n’s Production Webhook URL, it posts to a Relay ingest URL. Relay durably queues the request, retries it with backoff against your n8n webhook as the destination, and keeps a delivery log. Here’s what that buys you against each bug above, stated plainly — two of the four are things Relay can only make visible, not fix:
| n8n’s bug | Fixed? | What actually happens |
|---|---|---|
| Webhooks randomly stop firing, need a manual toggle | Yes | Relay receives the request first. While n8n's listener is down, the payload sits safely in Relay, gets retried with backoff, and lands in the DLQ (visible, manually replayable) if n8n never answers — instead of vanishing. |
| Multi-main activation failure permanently deactivates a workflow, no audit trail (#27416) | Yes | Same shape as the row above, but harsher: once this fires, the workflow doesn't just go quiet, it's permanently deactivated with no automatic recovery and no audit trail, so nobody notices until someone checks. Relay still receives every request in front of that dead webhook, queues it, retries with backoff, and lands it in the DLQ once retries exhaust — visible and replayable once a human notices and manually reactivates the workflow. Relay doesn't reactivate n8n's workflow and can't see the deactivation itself; what it does is keep the events alive, and its DLQ-growth alert (email, or a Slack webhook if the team has one configured) fires once retries start exhausting — which is usually how someone finds out. Fixed in n8n 2.17.0 — if you're not on that version yet in a multi-main queue-mode deployment, this is still live. |
| Self-hosted webhook silently stops responding, no root cause found (#11424) | Yes | Same shape as the first row, reported independently on a plain single-instance, self-hosted deployment. n8n closed the issue without ever finding a root cause; the only fix anyone found was deleting and recreating the webhook trigger. Relay in front of the same webhook queues and retries every request during that dead window and holds anything that never gets through in the DLQ, so recreating the trigger doesn't cost you the events that arrived while it was down. |
| API-activation never registers the webhook path (#21614) | No | Relay can't register n8n's own listener. Instead of a silently dead webhook, requests show up in Relay's delivery log as RETRYING → DLQ against a destination that keeps refusing — a real, timestamped failure signal instead of nothing. |
| n8n Cloud's 100-second Cloudflare timeout | Yes, partly | Relay acknowledges the sender in milliseconds and forwards asynchronously — Stripe/Shopify never see n8n's processing time, they see Relay's ack. If n8n itself then times out on Relay's forward, that attempt becomes a RETRYING/DLQ item Relay keeps retrying, rather than the sender's own delivery attempt failing outright. |
| Production webhook always returns 200 OK with nothing registered (#16339) | No | This is the sharpest limit. If n8n accepts Relay's forwarded request and answers 200 while doing nothing, Relay's delivery log will honestly show DELIVERED, because that's what happened at the HTTP layer. Relay can prove “we handed this to n8n and n8n said OK.” It cannot prove n8n's workflow actually ran. |
Not covered at all: WhatsApp/Meta’s webhook verification handshake (hub.mode, hub.challenge, hub.verify_token) is a separate, well-documented n8n pain point, but Relay doesn’t implement that handshake either. Don’t route a WhatsApp Business API verification step through Relay expecting it to work — it won’t.
One thing worth knowing before you rely on DLQ replay: Relay’s DLQ “Retry” button resends the stored request body with the original request headers, signature headers (stripe-signature, x-hub-signature-256, x-shopify-hmac-sha256) included, so an n8n workflow that verifies a signature itself will see the same header the original delivery carried. Two caveats remain, both about time rather than content:
- Timestamped signatures can still go stale. Stripe and others bind the signature to a timestamp and reject anything outside a tolerance window (Stripe’s default is five minutes). A replay sent long after the original failure can therefore still be refused as stale, headers and all — that is the destination’s clock, not something Relay withholds.
- Items that predate this feature have no headers to replay. DLQ rows written before header retention shipped never stored the map, so replaying one behaves the old way (body only). The confirm dialog tells you which of the two cases an item is in before you click.
Before you start: one constraint that matters more for n8n than most#
Relay validates every destination URL and rejects anything that resolves to a loopback or private address (this is an anti-SSRF control, not an n8n-specific restriction). If you’re self-hosting n8n on a machine that isn’t reachable from the public internet — localhost, a private LAN address, a Docker-internal hostname with no public DNS — Relay cannot reach it as a destination, for the same reason your original webhook sender couldn’t reach it either. You need a publicly resolvable URL for your n8n instance (n8n Cloud gives you one automatically; a self-hosted instance needs a reverse proxy, tunnel, or public DNS entry pointing at it) before Relay — or anything else on the internet — can deliver to it.
Setup, step by step#
This uses Relay’s existing sign-up and route-creation flow as it exists today. There is no n8n-specific UI yet — you’re using the same “New Route” wizard used for any destination.
- Get your n8n Production Webhook URL first. Open the workflow with the Webhook trigger node you want to protect. Make sure the workflow is activated — n8n only serves the Production Webhook URL (as opposed to the Test URL) once a workflow is active — and copy that Production URL from the node.
- Create a Relay account and a team. Sign up with email and password (there’s no magic-link or OAuth sign-in yet, so expect a normal password signup plus an email verification step). Once you’re in, you’ll be asked to name a team; any name works.
- Create a route. From your team’s Buffer → Routes page, click New Route and walk the 3-step wizard: name it after the sender (e.g. “Stripe → n8n”), paste your n8n workflow’s Production Webhook URL as the Destination (Relay defaults to 7 retries before a payload moves to the DLQ), then get your Relay ingest URL — treat the whole URL as a secret, and rotate it from the Routes table if it ever leaks.
- Repoint your webhook source at the Relay URL — not at n8n. Go into your webhook source’s own settings (Stripe’s Developers → Webhooks, Shopify’s notification settings, etc.) and replace the n8n Production Webhook URL you had it pointed at with the Relay ingest URL from step 3. Leave your n8n workflow’s own webhook node exactly as it is — Relay forwards to it, it doesn’t replace it.
From this point on, the flow is:
request path
sender → Relay ingest URL → Relay queues the request, retries with backoff on failure → n8n's Production Webhook URL → your workflow
What you’ll see once it’s live#
The delivery log (Buffer → Live Delivery Log, filterable down to just this route) shows every request Relay has received and what happened to it:
- QUEUED — received and durably stored, forwarding hasn’t completed yet.
- DELIVERED — n8n answered with a success status. This means n8n accepted the HTTP request, not that your workflow necessarily finished successfully (see GitHub #16339 above).
- RETRYING — the forward to n8n failed and Relay is backing off before trying again.
- FAILED / DLQ — retries ran out. The payload is now sitting in the dead letter queue rather than lost.
- TEST — a row generated by Relay’s own “Send test webhook” button, not real sender traffic.
The DLQ (Buffer → Dead Letter Queue) lists everything that exhausted its retries. Each row shows the route, the destination, and a Retry button that re-publishes the stored payload back through the same delivery path — once per item, and only if the payload was retained (payloads over 64KB aren’t stored, so there’s nothing to replay). A retry replays the original request headers too, so a signature check your n8n workflow performs (Stripe-Signature, X-Hub-Signature-256, X-Shopify-Hmac-SHA256) passes on replay the same way it did on the original delivery — except for a DLQ row created before header retention shipped, which has no headers stored against it; the confirm dialog states this per-row.
What this setup does not give you (yet)#
There’s no dedicated n8n node, no in-canvas status view, and no listing in n8n’s community-node registry. You’re using Relay’s general-purpose route flow, pointed manually at your n8n instance, the same way you’d point it at any other HTTP destination. If a first-class n8n integration ships later, it will build on top of exactly this same mechanism — it won’t need you to redo anything you set up here.