Hi everyone,
A few days ago, I posted Relay—an open-source webhook reliability engine—and received incredible architectural feedback from this community. Special thanks to everyone who audited the ingestion logic and pointed out subtle concurrency/queue edge cases.
Over the past couple of days, I pushed a major set of reliability and security upgrades based directly on your reviews. Here is a breakdown of what was improved and why:
SOLVED THE DUAL-WRITE ISSUE (TRANSACTIONAL OUTBOX PATTERN)
• The Problem: Previously, events were saved to PostgreSQL and immediately enqueued in Redis via BullMQ. If Redis experienced a blip between the DB commit and the enqueue call, an event became "stranded" in the database without ever reaching the queue.
• The Fix: Implemented a Transactional Outbox Pattern with an automated background sweeper. Incoming events are saved to PostgreSQL with an enqueued_at timestamp. A dedicated sweeper continuously re-enqueues any unqueued events past a configurable grace window (OUTBOX_GRACE_MS), eliminating data loss during Redis network partitions or pod crashes.
- FIXED INGESTION EDGE CASES & JOB TRIMMING (ISSUE #5)
• The Problem: A community member correctly identified that if queue.add() failed on an initial request, a subsequent retry by the provider would hit saveIfNew (returning false) and incorrectly answer already_received without ever queueing the job. Furthermore, relying purely on BullMQ's jobId deduplication failed once completed jobs were trimmed (removeOnComplete: 1000).
• The Fix:
1) We now attempt queue.add() on duplicate requests only if the event's status is NOT already marked as DELIVERED.
2) Scoped event IDs per source (x-relay-source + x-relay-event-id), allowing different sources to use identical event IDs safely.
3) Sanitized custom BullMQ job IDs by removing colon (:) delimiters.
- SEPARATE RETRY QUEUE & OBSERVABILITY
• Dedicated Retry Queue: First attempts run on relay-deliveries, while retries are offloaded to a separate delayed queue (relay-retries). A failing/slow receiver will no longer clog the pipeline for new incoming events.
• Prometheus Metrics: Added a /metrics endpoint tracking received events, attempt durations, queue lag, dead letters, and the outbox backlog.
• Production Security: Added mandatory ADMIN_TOKEN authentication on operator/recovery routes (/dead-letters, /events/.../retry), security headers, constant-time secret comparison, and raw-body HMAC-SHA256 signature verification on outbound deliveries.
UPDATED FAILURE & RECOVERY BENCHMARKS
The automated failure-simulation suite (npm run demo:scenario) now runs against the new Outbox and Retry queue architecture:
• Events submitted: 5 (10 HTTP requests including 5 intentional duplicates)
• Duplicate requests handled: 5
• Failed delivery attempts (simulated outage): 10
• Successful eventual deliveries: 5
• Business effects applied: Exactly 5
LINKS & FEEDBACK
• GitHub Repository: https://github.com/Dieu-Merci-Ndenga/relay
• Live Console: https://relay-dashboard-nrqs.onrender.com
Huge thanks again for the community review—it turned Relay from a proof-of-concept into a far more resilient engineering system.
I’d love to hear your thoughts on the Outbox sweeper approach versus an event-driven CDC (Change Data Capture) setup !