Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

guiwohl/relay

Open more actions menu

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Relay

Webhook delivery infrastructure. Register a destination endpoint, push events over the API, and Relay signs each delivery with HMAC-SHA256, retries failures with exponential backoff, dead-letters what won't deliver, and lets you replay any of it from a dashboard. Multi-tenant SaaS with session + API-token auth and Stripe billing.

Portfolio project — a real, working MVP, not a toy. The reliability core (signing, retry/backoff, idempotency, dead-letter, replay) is genuinely implemented and tested.

What it does

  • Sign — every delivery carries X-Relay-Signature: sha256=<HMAC> over "{timestamp}.{body}" with the endpoint's secret, so the destination can verify authenticity and reject replays.
  • Retry with backoff — failed deliveries retry up to 5 times with exponential backoff (0, 2, 4, 8, 16s), each attempt logged with its next_retry_at.
  • Dead-letter — once attempts are exhausted the event is marked dead-lettered.
  • Replay — a manual action re-runs delivery from a clean slate when the destination is healthy again.
  • Idempotent ingestion — an Idempotency-Key header dedupes retried sends.

Tech stack

Layer Choice
Framework PHP 8.4 · Laravel 12
Frontend Inertia 2 · React 19 · Tailwind · shadcn/ui (Laravel React starter kit)
Queue / worker Laravel Horizon + Redis (DeliverWebhook jobs)
Data PostgreSQL 18 · Redis
Auth Session (dashboard) · Sanctum bearer tokens (ingestion API)
Billing Laravel Cashier (Stripe, test mode) — Billable on the Tenant
Infra Laravel Sail · ./relay CLI · Pint · PHPUnit

Row-level multi-tenancy (tenant_id FK, a BelongsToTenant global scope).

Architecture

                    dispatch     ┌───────┐
  client ─POST─▶ Laravel app ──▶ │ redis │
                    │  job        └───┬───┘
                    │  inserts        │ pop
              ┌─────▼─────┐      ┌─────▼─────┐  signed POST
              │  pgsql    │◀─────│  horizon  │ ───────────▶ your endpoint
              └───────────┘  log └───────────┘   retry/backoff/dead-letter
                              every attempt
   dashboard (Inertia/React) ─▶ app    (only the app is exposed to the host)

Full design — data model, retry algorithm, signing scheme, idempotency — is in docs/decisions/0001-architecture.md.

Quick start

git clone https://github.com/guiwohl/relay && cd relay
cp .env.example .env
./relay artisan key:generate     # or paste an APP_KEY
./relay init                     # build, boot, install deps, build assets, migrate + seed

Open the dashboard at http://localhost:8081 (change with APP_PORT in .env). Horizon is at /horizon. The seeder creates demo@relay.test / password. Only the app is exposed to the host; pgsql/redis live on the internal Docker network. For a stable URL, point portless at the app container to get https://relay.localhost.

Common commands: ./relay horizon · ./relay test · ./relay lint · ./relay tinker · ./relay down. Run ./relay with no args for the full list.

The end-to-end retry/replay demo is scripted in docs/runbooks/local-dev.md.

Billing demo needs your Stripe test keys

Billing code is real (Cashier Checkout Session + signature-verified webhook). The live demo needs your own Stripe test-mode keys in .env (STRIPE_KEY, STRIPE_SECRET, STRIPE_PRICE_ID, STRIPE_WEBHOOK_SECRET). Automated tests don't call Stripe for checkout but exercise the webhook signature path for real, so ./relay test needs no keys.

Tests

./relay test runs the PHPUnit suite (SQLite in-memory — no services needed): signing is verifiable by a destination, backoff schedule + cap, retry→dead-letter, replay recovery, idempotency dedupe, auth + tenant isolation, and Cashier webhook signature verification (valid signature mutates state; tampered is rejected).

About

Webhook delivery infrastructure — HMAC-signed events with retry, backoff, dead-lettering and replay. Laravel · Inertia · React · Horizon · Docker

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages

Morty Proxy This is a proxified and sanitized view of the page, visit original site.