Skip to content

Repository files navigation

Relayforge

Relayforge is a small, production-minded webhook delivery service. It accepts idempotent events, signs outbound payloads with HMAC-SHA256, persists work in SQLite, retries recoverable failures with exponential backoff, and retains exhausted deliveries in a dead-letter state.

Why it exists

Webhook sending looks simple until a receiver times out, a client retries a request, or a worker crashes midway through a send. Relayforge makes those failure modes explicit:

  • idempotency is enforced per endpoint and client key;
  • dispatch is claimed transactionally before it is sent;
  • outbound requests have a strict timeout and a signed envelope;
  • non-2xx results are retried with capped exponential backoff;
  • stale claims become retryable after their visibility window expires.

Quick start

Requires Node.js 22 or newer.

cp .env.example .env
npm install
npm run dev

Create an endpoint:

curl -X POST http://localhost:3000/v1/endpoints \
  -H 'content-type: application/json' \
  -d '{"url":"https://webhook.site/your-id","secret":"replace-with-a-long-random-secret"}'

Enqueue an event with an idempotency key:

curl -X POST http://localhost:3000/v1/deliveries \
  -H 'content-type: application/json' \
  -H 'idempotency-key: order-1001-created' \
  -d '{"endpointId":"ENDPOINT_ID","eventType":"order.created","payload":{"orderId":"ord_1001"}}'

Run one dispatch batch:

curl -X POST http://localhost:3000/v1/workers/dispatch

API surface

Method Route Purpose
GET /healthz Liveness probe
GET /v1/endpoints List endpoint metadata
POST /v1/endpoints Register a signed callback endpoint
GET /v1/deliveries Inspect recent deliveries
GET /v1/deliveries/:deliveryId Inspect one delivery
POST /v1/deliveries Enqueue an idempotent event
POST /v1/workers/dispatch Dispatch a bounded batch

If ADMIN_TOKEN is set, the worker route requires the same value in the x-admin-token header.

Outbound envelope

The receiver gets a JSON body shaped as:

{
  "id": "delivery UUID",
  "event": "order.created",
  "occurredAt": "2026-08-09T12:00:00.000Z",
  "data": { "orderId": "ord_1001" }
}

The x-relayforge-signature header is sha256= followed by the HMAC-SHA256 digest of the exact request body. Compare it with a constant-time algorithm at the receiver.

Development

npm run check

The check combines strict TypeScript type checking, the Node test suite, and a production build. The CI workflow runs the same command.

Design notes

See docs/architecture.md for the execution model and SECURITY.md for operational boundaries.

Production considerations

Relayforge is deliberately a focused reference implementation. For a multi-node deployment, use PostgreSQL or another shared durable store, run dispatch through a process supervisor, enforce egress controls at the network layer, store endpoint secrets in a managed secret service, and expose metrics to your monitoring platform.

About

Resilient webhook delivery service with signed retries and a dead-letter queue.

Resources

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages