Skip to content

Resources · Reference architecture

Event-driven automation: a reference architecture

The design we start from when forms, payments, CRMs and schedules need to trigger work across your tools, sometimes with an AI step in the middle, without losing or doubling a record. It is a reference design, not a client system, and it keeps the same shape on n8n or in code; the queue behaviour it relies on is cited with the date we checked it.

Layer: all four, centred on Reason and Control

Sample data
Form webhookSignature checkedDone
Nightly scheduleChanged recordsDone
IngressStore, then return 200Done
Durable queueEvent id = keyRunning
Enrich workerModel step, schema checkDone
CRM workerAttempt 3 · backoffRetrying
Dead-letter listPayload + last errorFailed
ReplaySame event idNeeds approval
A form webhook is stored before ingress returns 200, and a nightly schedule adds changed records; both land in a queue keyed by event id. The enrich worker finishes; the CRM worker retries, then parks the job on the dead-letter list, where an operator replays it with the same key.

The problem

What this architecture solves

Point-to-point automations work until volume or failure arrives: a webhook fires twice, a CRM is down for a minute, a model call times out, and someone finds a duplicate contact or a lead that never arrived. This design treats every trigger as an event with an id, stores it first, and lets workers process it at their own pace, safe to retry and easy to replay.

  • No event is lost: it is stored before the sender gets its 200.
  • No write happens twice: every worker checks the event id first.
  • A failure lands on a list a person can read and replay, not in a log nobody opens.
  • An AI step is one worker among others, with its output checked against a schema.

Use it when several systems trigger work, volumes vary or a duplicate costs money. A single low-volume Zap that copies a form into a sheet does not need it.

Components

Components and the options for each

  • Event sources

    Form webhooks, payment and CRM events, and schedules that sweep systems without webhooks for changed records.

    • Webhooks from your tools
    • Stripe events
    • Scheduled sweeps
  • Ingress endpoint

    Verifies the signature, writes the raw event with its id and only then returns 200. No business logic lives here.

    • Cloudflare Workers
    • n8n webhook node
    • Next.js route on Vercel
  • Event log

    Every event as received, so a run can be traced and replayed from the original payload.

    • Cloudflare D1
    • Supabase Postgres
  • Durable queue

    Holds jobs until a worker succeeds, with a retry limit and a dead-letter list for jobs that run out of retries.

    • Cloudflare Queues
    • n8n in queue mode
    • Postgres job table
  • Workers

    Small steps that each do one thing (enrich, write to the CRM, notify) and check the event id before they write.

    • n8n workflows
    • Make or Zapier for simple steps
    • Python or TypeScript workers
  • Model step

    A worker that classifies, extracts or drafts; its output must pass a schema check before the next step uses it.

    • OpenAI
    • Anthropic
    • Google Gemini
    • Open-weight model you host
  • Idempotency store

    Which event ids have completed which writes, so a retry or replay skips work already done.

    • Supabase
    • Cloudflare D1
    • Keys on your CRM records
  • Dead-letter list and replay

    Jobs that ran out of retries, with payload, step and last error; an operator fixes the cause and replays with the same id.

    • Queue dead-letter queue
    • Admin page with replay
    • n8n error workflow

Data flow

How data moves, step by step

  1. 01A source fires: a signed webhook, or a schedule that finds changed records.
  2. 02Ingress verifies the signature, stores the raw event with its id and returns 200.
  3. 03The event becomes one or more jobs on the durable queue, keyed by event id.
  4. 04Workers pick up jobs; each checks the idempotency store before writing anything.
  5. 05A model step classifies or extracts; output that fails the schema check goes to a person, not onward.
  6. 06A failed write retries with backoff; after the last retry the job moves to the dead-letter list and the owner is alerted.
  7. 07The owner fixes the cause and replays; the same event id means finished writes are skipped.

How it works

Design decisions

  1. Mechanism 01

    Store, then acknowledge

    Senders retry when they do not get a quick 200, and some eventually give up. So ingress only verifies and stores before replying. The slow work happens later, from the queue, so a sender never waits on your CRM or a model.

    What's the alternative? Process inside the webhook call

    Fewer parts, until a slow step causes a timeout, the sender retries and the work runs twice.

  2. Mechanism 02

    The event id is the idempotency key

    Queues deliver at least once, so duplicates are normal rather than rare accidents. Every write is keyed by event id plus step name, and a worker that finds the key completed skips the write. Retries and replays become safe by construction.

    What's the alternative? Trust the sender not to repeat itself

    Fine in testing; in production the first network blip creates a duplicate contact or a double charge.

  3. Mechanism 03

    Failures are parked, not lost

    A job that runs out of retries moves to a dead-letter list with its payload, step and last error; without one, a queue deletes such messages for good. The owner sees a short, readable list and replays once the cause is fixed.

    What's the alternative? Retry forever

    Hides the failure, piles load on a broken system and delays everything queued behind it.

  4. Mechanism 04

    n8n or code, same shape

    n8n in queue mode already separates a main instance that receives webhooks from workers that run executions, which fits this design. Steps that need strict idempotency or heavy volume move to code workers on the same queue.

    What's the alternative? One giant workflow

    Easy to draw, hard to retry: a failure halfway forces a rerun of everything before it.

Reference diagram

The whole design on one diagram

Drawn to the same legend as our other reference architectures, so you can compare them box for box.
Event-driven automation · reference diagramReference design

Two webhooks and a nightly schedule reach an ingress that logs each event and queues it. An enrich worker and a model step feed a CRM writer that upserts with idempotency keys; jobs out of retries go to the dead-letter list, which alerts the ops owner to replay.

Diagram with 13 parts: Form webhook (source), Payment event (source), Schedule (source), Ingress endpoint (processing), Event log (system of record), Durable queue (processing), Enrich worker (processing), Model step (model), CRM writer (processing), Dead-letter list (control), Your CRM (system of record), Idempotency store (system of record), Ops owner (human).

Connections:

  • Form webhook → Ingress endpoint (signed POST)
  • Payment event → Ingress endpoint (event)
  • Schedule → Ingress endpoint (changed records)
  • Ingress endpoint → Event log (raw copy)
  • Ingress endpoint → Durable queue (event id)
  • Durable queue → Enrich worker (job)
  • Durable queue → Model step (job)
  • Enrich worker → CRM writer (enriched record)
  • Model step → CRM writer (checked fields)
  • CRM writer → Your CRM (upsert)
  • CRM writer → Idempotency store (done key)
  • CRM writer → Dead-letter list (out of retries)
  • Dead-letter list → Ops owner (alert)

How to read these diagrams

Source· in this diagram
Where a request or data enters: a chat widget, a WhatsApp message, a phone call, a webhook, a schedule or an approved document set.
Processing· in this diagram
Ordinary code we write and test: ingress endpoints, routing, retrieval, queues, workers and tool calls. It behaves the same way every time.
Model· in this diagram
A language, speech or embedding model call. Its output is treated as a draft and checked before it can reach a customer or a system.
Control· in this diagram
A gate that can stop, hold or reroute work: input checks, citation checks, send rules, transfer rules and dead letters.
Human· in this diagram
A customer or someone on your team. An arrow into a person is the answer, the escalation or the approval path.
System of record· in this diagram
Where state lives and survives a restart: your CRM, helpdesk or calendar through its API, a search index, a log.
  • Arrows run in the order data moves: left to right, or top to bottom on a phone.
  • A label on an arrow names what travels along it, such as a question, an event id or a ticket.
  • Named products are options from our build stack; “your … via its API” means the system you already run.
  • Each diagram is a reference design, not a drawing of any client’s system. Component choices are made per project.
Read the diagram as text
  1. Form webhook → Ingress endpoint (signed POST)
  2. Payment event → Ingress endpoint (event)
  3. Schedule → Ingress endpoint (changed records)
  4. Ingress endpoint → Event log (raw copy)
  5. Ingress endpoint → Durable queue (event id)
  6. Durable queue → Enrich worker (job)
  7. Durable queue → Model step (job)
  8. Enrich worker → CRM writer (enriched record)
  9. Model step → CRM writer (checked fields)
  10. CRM writer → Your CRM (upsert)
  11. CRM writer → Idempotency store (done key)
  12. CRM writer → Dead-letter list (out of retries)
  13. Dead-letter list → Ops owner (alert)

Platform

Platform capabilities this design uses

Build or buy

Build, buy or combine

Most teams start with a hosted automation tool, and many should stay there. The design starts to matter when failures cost money.
Build, buy or combine: when each option fits and what it costs you
OptionFits whenThe trade-off
Zapier or Make on their ownLow volume, few systems, and a duplicate or a missed run is an annoyance rather than a cost.Retry and replay follow the tool’s rules, and idempotency is hard to enforce across steps.
n8n on this reference designSeveral sources, an AI step, data kept on your server, and a team that likes visual workflows.You run n8n, or pay for n8n Cloud, and keep its queue, workers and error workflow healthy.
Code workers on a managed queueHigh volume, strict ordering per record, or writes where a duplicate is expensive.Changes need a developer, and the run log and replay page have to be built.

Rollout

How we roll it out

Typical sequence for a first build; the weeks are typical ranges, set per project at scoping.
  1. Week 1

    Event inventory

    List every trigger, how its sender retries, and what a duplicate or a miss would cost.

  2. Weeks 1–2

    Ingress, event log and queue

    Store-then-acknowledge endpoints and the queue with retry limits and a dead-letter list.

  3. Weeks 2–4

    Workers and the model step

    Idempotent workers, the schema-checked model step, and tests that replay real payloads twice.

  4. Weeks 4–5

    Run in parallel

    The new pipeline runs beside the old automation, and results are compared before the switch.

  5. After launch

    Own the dead letters

    A named owner, alerts and a short weekly look at what failed and why.

Vendor facts on this page, with the date we checked

  1. Delivery guarantees (at-least-once delivery) (opens in a new tab) · Cloudflare Docs · accessed
  2. Dead Letter Queues (opens in a new tab) · Cloudflare Docs · accessed
  3. Queue mode (opens in a new tab) · n8n Docs · accessed

Failure modes

What fails, and how it is handled

The sender delivers the same event twice
The idempotency key matches a completed write; the duplicate is acknowledged and skipped.
A downstream API is down
Retries with backoff and jitter; after the limit the job is parked on the dead-letter list and the owner alerted.
Events arrive out of order
Workers compare the record’s last-updated time and ignore an older event that arrives after a newer one.
The model step returns something unusable
The schema check sends the job to review, never onward, and keeps the raw output for debugging.
A schedule runs twice or overlaps
Each sweep takes a lock and records the last change it processed, so an overlap finds nothing new.
A bad deploy breaks a worker
Jobs fail into the dead-letter list instead of disappearing; after the fix, a bulk replay drains it.

Running cost

What drives the running cost

Drivers, not prices: vendor prices change, so we quote them per project with the date we checked.
Runs or executions
Hosted automation tools bill by task, operation or execution; splitting work into many tiny steps multiplies the count.
Model calls
Only steps that need judgement call a model; deterministic steps stay in code.
Queue and storage
Small per event; grows with volume and with how long the event log is kept.
Retries
A failing downstream system multiplies calls; backoff and a retry limit cap it.
Time on the dead-letter list
Small when things work; a growing list is the early warning that something upstream changed.

Defaults

Defaults we ship

  • Store before acknowledging; ingress holds no business logic.
  • Event id plus step name as the idempotency key on every write.
  • Retry limits with backoff, then a dead-letter list with replay.
  • A schema check on every model output before it is used.
  • A named owner alerted with a link to the failed run.
  • Secrets in a secrets manager, never inside a workflow export.

Limits

Limits and variants

  • Not instant: a queued job may run a moment later, so a reply that must be immediate belongs in the request path.
  • Queues do not offer exactly-once delivery; correctness comes from idempotent writes.
  • Systems without webhooks need scheduled sweeps, which add delay up to the sweep interval.
  • Variant, n8n only: webhook processors and queue-mode workers on your server, with an error workflow feeding the dead-letter list.
  • Variant, code workers on Cloudflare Queues: for high volume or strict ordering per record.

Configuration

What the configuration looks like

Pipeline configuration (Sample data)
pipeline: lead-intake
sources:
  - webhook: site-form          # signature: hmac-sha256
  - schedule: crm-changes       # nightly, from the last change cursor
ingress:
  store_then_ack: true
queue:
  key: "{event_id}:{step}"
  max_retries: 5
  backoff: exponential-with-jitter
  dead_letter: lead-intake-dlq
workers:
  - enrich: { reads: [company-lookup] }
  - classify: { model: true, output_schema: lead.v2 }
  - crm_upsert: { idempotent: true }
alerts:
  dead_letter_over: 0
  owner: ops-owner

FAQ

Frequently asked questions

When does an automation need a queue instead of a direct webhook-to-CRM flow?

When several systems trigger it, volumes jump, a step is slow (a model call, a busy API) or a duplicate costs money. If one form copies into one sheet and nobody minds a rare miss, a direct flow is fine and cheaper to keep.

What happens to events that arrive while our CRM is down?

They wait. Each event is already stored and queued, so the CRM worker retries with backoff; if the outage outlasts the retries, jobs park on the dead-letter list and are replayed once the CRM is back.

Can an AI step sit in the middle of an event-driven workflow safely?

Yes, as one worker with a narrow job: classify, extract or draft. Its output must pass a schema check before the next step uses it, it never writes to a system directly, and anything that fails goes to a person with the raw output attached.

Does this design still work if our team builds in n8n?

Yes. n8n’s queue mode already separates the instance that receives webhooks from the workers that run executions. We add the event log, idempotency keys and a dead-letter list around it, and move only the strictest steps to code.

How do we replay a failed job without creating duplicates?

Replay the original event with its original id. Each write checks the idempotency store, so finished steps are skipped and only the failed ones run again. Replaying a fresh copy with a new id is what creates duplicates.

Who should own the dead-letter list?

One named person on your operations side, with a backup. They get an alert when the list grows, fix the cause or ask us, and replay. A dead-letter list nobody owns is a slower way of losing data.

Next step

Have a workflow in mind? Let’s scope it together.

Book a free 30-minute strategy call. Bring one process you want to automate and we will talk through scope, integrations and a sensible first step.

Free 30-minute call · no commitment

Send an RFP or security questionnaire