The missing layer between webhooks and your app. One binary. Verify, queue, deliver — nothing is lost.
Stripe sends a webhook. Your server is deploying. The event is gone.
qhook sits between webhook providers and your app. It verifies signatures, persists every event before responding, and delivers to your handlers with retry and dead-letter queues. Your webhook source gets a 200 in under 500ms. Your app processes events when it's ready.
Provider → qhook (verify → queue → ACK) → your handler
↓ ↑ retry
persist circuit breaker
cargo install qhook# qhook.yaml
database:
driver: sqlite
sources:
stripe:
type: webhook
verify: stripe
secret: ${STRIPE_WEBHOOK_SECRET}
handlers:
billing:
source: stripe
events: [invoice.paid, customer.subscription.updated]
url: http://localhost:3000/webhook
retry: { max: 5 }qhook start
# → Listening on :8888
# Point Stripe webhook URL to http://yourhost:8888/webhooks/stripeThat's it. Stripe webhooks are verified, queued, and delivered with retry. If your handler is down, events wait in the queue and are retried with exponential backoff.
Lightweight. A single 16 MB binary. No Redis, no RabbitMQ, no external message broker. SQLite for development, Postgres or MySQL for production.
Dev to prod, same tool. Start with SQLite locally. Deploy to Cloudflare with D1, or scale with Postgres. One line change. Same config, same binary, same behavior.
# Local dev # Cloudflare # Scale
database: database: database:
driver: sqlite driver: d1 driver: postgres
database_id: ... url: ${DATABASE_URL}Estimated throughput (based on DB write characteristics — run your own benchmarks with scripts/bench-cloudflare.sh or tests/bench.sh for actual numbers):
| Driver | Est. throughput | Best for |
|---|---|---|
| SQLite | ~1K events/sec | Local dev, single instance |
| D1 | ~500 events/sec | Cloudflare deploy, low-medium traffic |
| Postgres | ~10K+ events/sec | Production, multi-instance |
13 webhook providers verified. Stripe, GitHub, Shopify, Twilio, Paddle, PagerDuty, Grafana, Terraform Cloud, GitLab, Linear, Standard Webhooks, HMAC, AWS SNS. IP allowlisting per source.
At-least-once delivery. Events and jobs are persisted in a single transaction before ACK. If qhook crashes, the webhook source retries and nothing is lost.
Production ready. Prometheus metrics, health checks (/health), Slack/Discord alerts, rate limiting (GCRA), circuit breaker, graceful shutdown, OpenTelemetry tracing.
qhook does more than receive and forward. Explore when you need it:
| Need | Feature | Guide |
|---|---|---|
| Fan out one event to multiple handlers | Multi-handler routing | Configuration |
| Consumer pulls events instead of push | Pull-mode queues | Pull-Mode Queues |
| Webhook → build → deploy → rollback | Workflow engine | Workflows |
| Send webhooks to your customers | Outbound webhooks | Getting Started |
| Filter events by payload content | JSONPath filtering | Filtering |
| Scale to millions of events/month | Postgres + multi-instance | Scaling Guide |
qhook start # Start server
qhook status # Overview at a glance
qhook tail # Stream events in real time
qhook inspect <EVENT_ID> # Full lifecycle of an event
qhook validate # Check config before deployAll CLI commands | Remote mode for managing deployed instances
cargo install qhook # From crates.io
docker pull ghcr.io/totte-dev/qhook # Docker image (~16 MB)totte-dev.github.io/qhook — Getting started, configuration, deployment guides, and more.
This project is developed by a solo engineer with AI pair programming (Claude Code). All code is reviewed, tested (400+ tests), and the architecture decisions are human-driven. AI accelerates implementation; design and quality ownership remain with the maintainer.
Skeptical? The entire codebase is open — read it yourself or let an AI review it for you.
Apache-2.0. See LICENSE.