Webhook DLQ & replay

Obsidian Dynamics Limited

Catch failed webhooks before they become incidents.

Sits between your providers and your app: durable ingest, bounded retries, and replay — without touching the provider.

  • 202 only after Postgres persistence — not after your destination responds
  • Exponential backoff, jitter, and DLQ when policy exhausts
  • Replay any failure with full lineage — no re-wiring the provider

Duplicates are possible by design (retries, at-least-once); downstream idempotency is recommended.

POST /ingest/… → 202 Accepted → verify → forward → retry → DLQ → replay

  • Fast ingest acknowledgment
  • Durable event capture
  • Exponential retries + jitter
  • Dead-letter queue
  • Manual replay
  • Slack alerts

Built for

Solo founders · Backend & platform engineers · Teams on Stripe, GitHub, Clerk, Resend, Shopify · Custom webhook producers

How it works

Receive, retry, replay.

01

Receive

Point your provider at a stable Charon URL. We acknowledge fast, persist the payload, and hand off to the background — your destination's latency never touches the critical path.

02

Retry

Exponential backoff with jitter. Transient 5xx and timeouts get another chance; clear 4xx fails fast.

03

Replay

When policy exhausts, the event lands in DLQ with full context. Fix the destination, replay: a new delivery chain tied to the original — no asking the provider to resend.

Product

A narrow layer between providers and your application.

Webhook insurance: visibility, retries, DLQ, and replay for the path that carries your revenue.

Event stream

Every ingress becomes a durable record.

Headers, raw body, content type, and correlation IDs land in one place. Scan what arrived, filter by endpoint or provider, and trace an ID across retries without digging through logs.

events / streamprod
endpoint_livelast 24h · 412 events

evt_1a9

Stripe · invoice.paid

Delivered

evt_8c2

GitHub · workflow_run

Retrying

evt_4ff

Clerk · user.updated

Verified

Delivery attempts

Each forward is explicit, timed, and inspectable.

No anonymous retries. Every POST to your app is an attempt row: latency, HTTP family, retryability, and a bounded response preview — the same facts your on-call will ask for.

evt_8c2 / deliveriesprod

Attempt chain

  • #4 · in flight

    POST → 504 · 12.4s

    backoff +8m
  • #3

    502 · 980ms

  • #2

    200 · 210ms

policy: exponential · max 8 · jitter ±20%

Failure triage

Dead-lettered events stay in an inbox, not in limbo.

When policy exhausts, the event lands in DLQ with context intact. Triage by status code family, endpoint, or provider — then decide: fix the destination, adjust policy, or replay.

failures / dlqprod
502/504endpoint:liveStripe
evt_8c2DLQ

Exhausted after 8 attempts · last error: upstream timeout

Replay controls

Replay what broke — with lineage, not guesswork.

Manual replay issues a new event and delivery chain while preserving ties to the original. Recover from bad deploys or transient auth drift without asking Stripe to resend.

replay / lineageprod

Source

evt_8c2

Original attempts preserved

Replay

evt_8c2_r1

New delivery chain · same payload

Verification

Inbound trust without theatrics.

Stripe and GitHub adapters, plus generic HMAC where you bring your own secret. Timestamp windows where the format allows. We state semantics plainly: at-least-once — your handlers stay idempotent.

verification / stripeprod
Signature verifiedtolerance 300s
stripe-signature
t=1724…, v1=••••
Charon-Event-Id
evt_1a9

Secrets encrypted at rest · compared in constant time

Security & trust

Practical controls for infrastructure-shaped teams.

No theatre. What ships: cryptography, isolation, and honest delivery semantics.

  • At-least-once semantics

    Duplicates can happen. Dedupe with provider IDs or Charon delivery headers.

  • HMAC verification

    Stripe and GitHub adapters, plus generic HMAC where you bring the secret. Constant-time compares; Stripe timestamps windowed.

  • Encrypted secrets

    Signing secrets and destination auth are encrypted at rest. Nothing sensitive echoed back from the API.

  • Per-endpoint delivery policy

    Timeouts, retry budgets, and backoff are explicit per destination — no hidden global defaults.

  • Tenant isolation

    Every query is tenant-scoped. DLQ, replays, and exports stay inside the workspace boundary.

  • Operator surface

    Secret-gated ops endpoint, Prometheus metrics, and a DLQ taxonomy SREs can act on without spelunking logs.

Pricing

Limits you can read in plain numbers.

Free tier is full-featured on reliability — retries, DLQ, replay — so you can evaluate honestly before scaling. Paid plans open signup and redirect to Stripe Checkout.

Free

Run one real endpoint with the full pipeline: durable capture, retries, DLQ, replay, and exports — so you can prove value before scaling.

$0

  • 1 ingest endpoint
  • 2 projects
  • 2 API keys
  • 10,000 ingested events / UTC day (tenant total)
  • Bounded retries with backoff · dead-letter visibility · manual + batch replay
  • Slack, email, or HTTPS webhook alert rules (bring your own channels)
  • Destination health probe, test delivery, optional DLQ-streak circuit breaker (auto-pause)
  • CSV export up to 2,000 rows per download (per request; configurable by operator)
Create free account

Pro

Most teams

For teams running multiple ingress surfaces and steady webhook volume — same product, higher safe throughput.

$19/ month

$190/yr ($15.83/mo billed annually)

  • Up to 10 ingest endpoints
  • 15 projects
  • 25 API keys
  • 500,000 ingested events / UTC day (tenant total)
  • Same product surface as Free — higher ceilings so you can run staging + production endpoints without splitting tenants
Subscribe — monthlySubscribe — annual

Team

When webhook traffic and surface area grow — higher per-day ingest ceilings and more projects without changing how you operate Charon Gate.

$49/ month

$490/yr ($40.83/mo billed annually)

  • Up to 50 ingest endpoints
  • 50 projects
  • 100 API keys
  • 5,000,000 ingested events / UTC day (tenant total)
  • Same delivery, DLQ, replay, and alerting model as Pro — scaled for platform teams
Subscribe — monthlySubscribe — annual

Events are purged on a rolling schedule (14 days by default; adjustable with RETENTION_DEFAULT_DAYS).

Keep the events your product depends on visible and recoverable.

When deploys wobble or rate limits bite, Charon holds the line: capture first, retry with discipline, and replay without re-wiring the provider.