n8n handles workflow logic. Delivery guarantees need a separate layer.
Workflow engines like n8n decide what should happen and when. Delivery guarantees — retries, idempotency, dead-letter handling, replay — are a separate architectural concern. Here's why the two layers work together rather than collapsing into one tool.
When an n8n workflow fires, two things have to happen for the automation to deliver value. The workflow has to execute its logic correctly — read the right inputs, branch through the right conditions, transform the data the right way. And the result has to reach its destinations reliably — retried when it fails, deduplicated when it retries, captured when it can't be retried, traceable when something goes wrong downstream.
n8n is built for the first problem. It isn't built for the second. That isn't a flaw; it's a category boundary. Workflow engines and delivery layers solve different problems, and the architectures that make a workflow engine pleasant to use are not the architectures that make a delivery layer reliable.
The trap is treating these as a single problem. Teams ship workflows that handle logic beautifully and assume the delivery side is "the same workflow." It isn't. The gap shows up later, in production, usually when a customer's data has been silently dropped or duplicated in a downstream system.
What workflow logic actually means
Workflow logic is the part of an automation that describes intent. A trigger fires when a specific event happens. A branch decides which path the data should take based on its content. A transformation reshapes the data into what the next step expects. A sequence ensures one step finishes before the next begins.
n8n is especially good at this layer. The visual builder makes the logic legible to people who didn't write it. The node ecosystem covers most of the common transformations and triggers. Self-hosting gives teams control over where workflows run and how credentials are stored. The execution model is fast enough for most real-time automation use cases, and the JSON-serialized workflow format makes workflows version-controllable as source code.
The 2.0 release included several production-hardening changes at this layer: SQLite pooling for performance, isolated task runners for security, and a Save-and-Publish model that prevents accidental production deployments. These are real improvements to the workflow engine. They don't change what category of tool n8n is.
The work of workflow logic is decided when the workflow is written. The author defines what should happen, in what order, under what conditions. The engine's job is to execute that definition faithfully when triggered.
What delivery guarantees actually mean
Delivery guarantees are the properties that make a distributed event actually arrive at its destination. They include retries with exponential backoff and jitter, so transient failures don't become permanent data loss. Idempotency keys, so retries don't create duplicates in downstream systems. Dead-letter handling, so events that exhaust retries are captured for investigation rather than silently dropped. Ordering guarantees where the use case demands them. Observability that survives the difference between "the workflow succeeded" and "the destination actually received the data." Replay capability, so events that fail can be retried later from the same state.
These properties don't come from the workflow definition. They come from the infrastructure underneath the workflow. A workflow that says "send this to HubSpot" has stated an intent; whether HubSpot received it, whether it received it exactly once, whether the team can prove either of those after the fact, are all separate questions.
The work of delivery guarantees is decided at runtime. The system has to detect what failed, decide what to retry, prevent duplicates during the retry, capture what couldn't be retried, and surface all of this in a way that operators can act on. None of this is in the workflow definition because none of it is knowable in advance.
Why n8n is shaped for workflow logic, not delivery infrastructure
The architectural choices that make n8n a good workflow engine are choices that constrain its ability to be a delivery layer. None of them are mistakes; they're the right calls for the problem n8n is solving.
n8n's retry mechanism is per-node and modest in scope. The "retry on fail" setting on individual nodes handles transient errors like network timeouts and rate-limit responses with a few attempts and short delays. This is enough for many automations. It is not the same as a delivery layer's retry policy, which has to handle minute-scale backoffs, day-scale retention of failed events, and per-destination retry budgets that don't conflate transient outages with permanent failures.
Execution is fail-fast by default. When a node fails, the workflow stops at that node. The author has to wire up Continue-on-Fail branches and Error Trigger workflows explicitly to keep the rest of the workflow running. This is the right default for logic — you don't want a workflow to silently skip a step — but it's the wrong shape for delivery, where one destination failing should not block delivery to other destinations.
Idempotency is the workflow author's problem. n8n does not natively track which events have been delivered to which destinations across retries. Teams that need this build idempotency tables in their own databases, generate request IDs in code nodes, or rely on the destination system's deduplication if it has any. Each of these works at small scale and degrades at production scale because the deduplication state lives outside the workflow engine.
The execution log is per-execution, not per-event-across-attempts. If a workflow runs, fails, runs again, and succeeds, the log shows two executions. Reconstructing the full delivery history of a single event — first attempted at T+0, failed, retried at T+30, succeeded — requires correlating executions by some key the workflow author had to choose to track. The information is recoverable but not native.
Error workflows fire when a workflow errors. They are a separate workflow you wire up to handle the failure path, often for alerts or custom failure handling. n8n also lets teams manually retry failed executions from the execution log. But neither of those is the same as an automatic, durable, per-destination delivery layer that owns retry scheduling, deduplication state, dead-letter capture, and replay across destinations.
What teams typically do to fill the gap
Teams running n8n in production at scale tend to converge on a similar pattern of additions. They wrap retry logic in code nodes for destinations where the per-node retry isn't sufficient. They build idempotency tables in Postgres or Redis, populated by workflow ID and event ID, checked at the top of every workflow that writes to a destination. They route Error Trigger workflows to incident channels and on-call rotations. They add observability through external tools — Datadog, Sentry, custom log shippers — to surface the silent-failure case where the execution log reports success but the destination didn't actually receive the data. They version-control workflow JSON in Git, with separate staging instances for testing changes.
Each of these is a real improvement. None of them is the same as having a delivery layer. The result is a workflow engine that does workflow logic plus a hand-built collection of delivery primitives spread across code nodes, sidecar databases, error workflows, and external tools. The collection grows with the workflow count, the maintenance load grows with the collection, and the team eventually arrives at the realization that they've rebuilt a partial delivery layer in a workflow engine.
This is the same trajectory hand-rolled webhook handlers follow. The first version is a simple POST. The second version adds basic retries. The third version adds an idempotency table. The fourth adds a dead-letter queue. At some point the team is maintaining a small distributed system embedded in their workflow code, and the cost of that maintenance starts to compete with the value of the workflows themselves.
The "layer together" pattern
The architectural alternative is to keep the two concerns in two layers. The workflow engine decides what should happen and when. The delivery layer makes sure it actually happens and recovers when it doesn't. The workflow engine emits an event to the delivery layer; the delivery layer handles retries, idempotency, dead-letter capture, observability, and replay; the workflow engine doesn't have to model any of that internally.
This is the same pattern that separates application logic from a message queue, or application code from a database transaction. The workflow author keeps their workflow legible and focused on intent. The delivery layer keeps the runtime guarantees consistent across destinations. Neither system has to do the other's job.
The two layers work together rather than competing. n8n's strengths — visual logic, broad node library, self-hosting, version control — are unaffected by adding a delivery layer underneath it. The delivery layer's strengths — retries, idempotency, observability across attempts — are unaffected by what workflow engine is feeding it. This is the shape Meshes is designed around: workflow tools emit events, and Meshes owns the outbound delivery path. The teams that get this layering right tend to ship more reliable automations with less custom code, because each layer does only the work it's shaped for.
When the layering matters and when it doesn't
The layering doesn't matter for every workflow. A workflow that sends a Slack notification on a non-critical event can fail occasionally without business impact. A workflow that backfills reporting data from a stable source can tolerate the per-node retry mechanism. A workflow that runs once a day and writes to a system the team controls end-to-end probably doesn't need a separate delivery layer.
The layering matters when the workflow touches customer state, revenue events, or downstream systems where missing or duplicate data has business consequences. A signup that doesn't reach the CRM means a sales rep doesn't follow up. A payment failure that doesn't reach the support tool means the support team doesn't see it. A subscription cancellation that doesn't propagate to marketing automation means the customer gets emailed offers for a product they no longer use. For these workflows, the delivery guarantees aren't optional — they're the difference between an automation that works and an automation that quietly breaks the business while reporting success.
The question worth asking before assuming the workflow engine is enough is: when this workflow fails at the destination — not at the node, at the destination — how do I know, how do I recover, and how do I prove it happened? If the answer involves more than the workflow engine, the workflow engine isn't the whole solution.
Meshes is the outbound event routing layer that handles retries, idempotency, dead-letter capture, and replay for events that n8n and other workflow engines emit — so the workflow stays focused on logic and the delivery layer handles the rest.Start free
Frequently asked questions
Does n8n handle retries? n8n supports per-node retries through the "retry on fail" setting, which retries individual nodes a configurable number of times with delays between attempts. This is appropriate for transient failures like network timeouts. It is not the same as a delivery layer's retry policy, which handles longer backoffs, durable retry queues, per-destination retry budgets, and recovery across full workflow restarts.
What is the difference between workflow logic and delivery guarantees? Workflow logic is the part of an automation that describes intent — triggers, branches, transformations, sequencing. Delivery guarantees are the runtime properties that ensure events actually reach their destinations — retries, idempotency, dead-letter handling, ordering, observability, replay. Workflow engines are built for the first; delivery layers are built for the second.
Can n8n prevent duplicate events from reaching a destination? Not natively. n8n does not maintain a record of which events have been successfully delivered to which destinations across retries. Teams that need deduplication either rely on the destination system's own idempotency support, build idempotency tables in their own databases, or generate request IDs in code nodes and check them on every execution. Each approach works at small scale; none is equivalent to a delivery layer with native idempotency.
Why don't workflow engines just include delivery guarantees? The architectures that make workflow engines pleasant to use — visual node-based execution, per-execution logging, fail-fast defaults, declarative workflow definitions — are not the architectures that make delivery layers reliable. Delivery guarantees require durable per-event state, retry queues that survive engine restarts, deduplication tracking across attempts, and dead-letter capture that's separate from workflow execution. Bolting all of this into a workflow engine compromises the workflow engine's clarity without producing as good a delivery layer as a purpose-built one.
When do I need a delivery layer underneath n8n? When the workflow touches customer state, revenue events, or downstream systems where missing or duplicate data has business consequences. Workflows that send non-critical notifications, run batch reporting jobs, or operate end-to-end on systems the team controls usually don't need a separate delivery layer. Workflows that move user signups, payment events, subscription changes, or support tickets between business-critical systems usually do.
Does adding a delivery layer mean replacing n8n? No. The two layers work together — the workflow engine continues to handle workflow logic, and the delivery layer handles the runtime guarantees for outbound events. The workflow author's experience inside n8n is largely unchanged; the difference is what happens to events after they leave the workflow.