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

jenksed/switchyard

Open more actions menu

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

41 Commits
41 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Switchyard — self-hosted webhook operations

Latest release CI Elixir 1.19 Phoenix 1.8 PostgreSQL 17 License Apache 2.0

Self-hosted webhook operations: receive, inspect, route, replay, and diagnose deliveries on your own infrastructure.


Get running in 60 seconds

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:4000

Open http://localhost:4000 and click Create an endpoint. bin/setup is safe to run repeatedly.

Port clash? If 5432 is taken:

POSTGRES_PORT=55432 docker compose up -d db
export POSTGRES_PORT=55432

What it looks like

Workspace overview
Switchyard workspace overview
Event stream & inspector
Switchyard event stream and request inspector
Operations & health
Switchyard operations page
Create endpoint
Switchyard create endpoint form

What Switchyard does

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 localhost via 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, switchyard CLI, 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.

The diagnostic loop

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]
Loading
  1. Create an endpoint; copy the ingest URL.
  2. Send any HTTP request to the ingest URL and watch it appear live.
  3. Route it with an immutable draft, dry-run against a captured event, then activate.
  4. 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
  5. Fail & replay — repair the receiver and replay; the full history is preserved.
  6. Export a sanitized receipt for your incident log.

For a complete walkthrough see docs/quickstart.md.

How it is built

  • 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.

Deployment

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/.

Verification

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 gate

Release 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.

Documentation

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

Contributing

Read AGENTS.md for the project operating manual, coding standards, and release discipline.

License

Apache License 2.0. See LICENSE.

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