Every event is accepted and stored here first — then forwarded. If your API is down, webhooks wait in queue instead of vanishing. Nothing is dropped; delivery catches up when you are back online.
No queue — if the API is down, events are gone; nothing replays when it comes back.
API up — synchronous path
Configure multiple forwarders so the same stored webhook is delivered to every target URL — like copying one inbound event to several APIs. Each forwarder has its own BullMQ queue; if one target is down, only that lane backs up while the others keep draining. Per target, delivery order matches ingest order: FIFO — first webhook saved is the first POST sent when that forwarder is up.
Both forwarders up — jobs flow Q → POST
Point an extra forwarder at staging, a local tunnel, or a mock while your live lane keeps posting to the real service. You can replay stored payloads, break handlers on purpose, and ship changes on your own schedule — no need to pause ingest or declare downtime for a drill. Each queue stays isolated, so experiments and retries in one lane do not starve the others. Less maintenance mode, fewer “API is down” moments for customers, and the same stored event can feed both safe tests and production delivery.
Each forwarder gets its own BullMQ queue and worker — no cross-talk.
fifoDeliveries are written on the webhook document before jobs are added — no empty-doc race.
atomicSource and forwarder resolution cached in Redis — invalidated on any CRUD.
60s ttlWhatsApp callbacks use /v1/webhooks/whatsapp/src_*
human idsMany WhatsApp apps — each source has its own Meta handshake token.
metaExponential backoff, TTL expiry, simulate ingest, per-queue pause and inspect.
opspayment_intent.succeeded invoice.payment_failed charge.refunded
These aren't just events. They move money. The old model sends them straight to your API — if it blinks, the signal is gone and your business logic never runs. Relay vaults every payment event first, then delivers when your service is healthy.
Top row: no relay. During outage, gold payment packets hit a dead endpoint and burst — gone. Bottom row: Relay vault buffers every event; gold packets drain automatically when the API recovers.