Self-hosted webhook operations: receive, inspect, route, replay, and diagnose deliveries on your own infrastructure.
You need Git, Docker, and Erlang/OTP + Elixir (see .tool-versions).
git clone git@github.com:jenksed/switchyard.git
cd switchyard
bin/setup # starts PostgreSQL, installs deps, migrates, builds assets
bin/dev # serves http://localhost:4000Open http://localhost:4000 and click Create an endpoint. bin/setup is safe to run repeatedly.
Port clash? If
5432is taken:POSTGRES_PORT=55432 docker compose up -d db export POSTGRES_PORT=55432
Workspace overview
|
Event stream & inspector
|
Operations & health
|
Create endpoint
|
Switchyard is a control point for the webhooks hitting your services. It sits between providers and your apps so you can see exactly what arrived, decide where it goes, and fix what broke.
- Capture everything — exact bytes, malformed bodies, empty payloads, binary uploads. No request is silently dropped.
- Inspect live — watch events stream in, inspect headers and body, with secrets masked by default.
- Route intentionally — draft immutable routing versions with match/skip/label/send/stop actions, or fall back to fan-out.
- Deliver safely — remote HTTPS destinations or
localhostvia an authenticated WebSocket relay. Private networks are never dialed from the server. - Replay & recover — retry, replay, or cancel deliveries. Full durable attempt history survives restarts.
- Operate as a team — workspaces, role-based access, audit trail, encrypted secrets, and shareable evidence links.
- Automate — stable REST API v1,
switchyardCLI, SSE event streaming, and sanitized JSON/Markdown/HTML receipts. - Run anywhere — one non-root, read-only application image across dev, single-node team, and multi-node team profiles.
flowchart LR
P[Provider] -->|POST /in/token| I[Ingest]
I -->|exact bytes, 202 after commit| E[(Event<br/>PostgreSQL)]
E --> S[Live stream<br/>& inspector]
E --> Q{Route<br/>evaluator-v1}
Q --> D{Deliver selected}
Q -->|labels + decision| S
D -->|remote| R[HTTP destination]
D -->|localhost| Y[Relay client]
R -.->|500 → retry / replay → 200| E
Y -.->|at-least-once| L[Local target]
E --> C[Sanitized receipt]
- Create an endpoint; copy the ingest URL.
- Send any HTTP request to the ingest URL and watch it appear live.
- Route it with an immutable draft, dry-run against a captured event, then activate.
- Forward to a remote destination or run a local relay:
mix switchyard.relay --server ws://localhost:4000 --token rel_… --target http://127.0.0.1:PORT
- Fail & replay — repair the receiver and replay; the full history is preserved.
- Export a sanitized receipt for your incident log.
For a complete walkthrough see docs/quickstart.md.
- PostgreSQL is the source of truth. PubSub only carries notifications.
- At-least-once delivery. Duplicates are possible; exactly-once is not claimed.
- Durable work runs on Oban — nothing important lives only in memory.
- Localhost delivery goes through the relay so the server never dials private networks.
- Thin web layer; domain contexts own behavior.
See docs/adr/ for the full architectural reasoning.
Three profiles share one immutable application image:
| Profile | How to run |
|---|---|
| Single-node development | bin/setup + bin/dev (or compose.yaml) |
| Single-node team | compose.team.yaml + TLS proxy + external SMTP |
| Multi-node team | compose.cluster.yaml — encrypted gossip, rolling upgrades, rehearsed rollback |
Full details: docs/v0.9/PROFILES.md. Operational runbooks live at docs/runbooks/.
mix check # format, compile (warnings as errors), Credo, security, tests
mix check.all # everything above plus Dialyzer
bin/verify-v0.9 # full v0.9 operator exit gateRelease gates chain their predecessors, so bin/verify-v0.9 re-proves the complete tree.
The v0.9 tested-limits record (docs/v0.9/TESTED_LIMITS.md) includes a full two-hour soak at 19.74 events/s sustained on Apple M1 Pro / PostgreSQL 17.
docs/quickstart.md— Switchyard in five minutesdocs/v0.9/PROFILES.md— deployment profilesdocs/api/v1/README.md— stable API v1 referencedocs/cli/README.md—switchyardCLI referencepriv/openapi/switchyard-v1.yaml— OpenAPI 3 artifactdocs/runbooks/README.md— install, upgrade, rollback, troubleshoot, maintaindocs/v0.9/TESTED_LIMITS.md— measured performance boundariesdocs/PROJECT_PLAN.md— product roadmap
| Stop | Theme | Status |
|---|---|---|
| v0.1–v0.8 | Diagnostic loop → operational collaboration | ✅ Complete |
| v0.9 | v1 release candidate: multi-node, deployment profiles, tested limits, contract freeze | 🔶 Release candidate |
| v1.0 | Stable Switchyard (stability contract) | Next |
| v1.1 | Signal View — experimental operational lens | Planned |
Read AGENTS.md for the project operating manual, coding standards, and release discipline.
Apache License 2.0. See LICENSE.



