How It Works
Sparrow accepts webhook registrations and event definitions, fans out events to matching subscribers, and delivers them reliably with retries and health tracking.
The Full Flow
Section titled “The Full Flow”-
Register an event type — tell Sparrow what events exist in your system.
-
Register a webhook — provide a URL and the events it should receive. Sparrow creates subscriptions automatically.
-
Push an event — when something happens, send the event payload to Sparrow:
Terminal window curl -X POST http://localhost:8080/webhook.EventService/PushEvent \-H "Content-Type: application/json" \-d '{"namespace": "default","event": "order.created","payload": {"order_id": "ord_123", "total": 49.99}}' -
Sparrow fans out — the event worker finds all active subscriptions matching the event name and namespace, applies any payload transforms, and creates a delivery job for each.
-
Webhook delivery — the webhook worker sends an HTTP POST to each URL with the payload, HMAC signature (if configured), and Sparrow headers. Failed deliveries are retried with exponential backoff.
-
Track results — query delivery status, health metrics, and error categories through the API or the web UI.
Push Event ──→ Event Worker ──→ Find Subscriptions ──→ Create Deliveries │ v Webhook Worker │ │ Success Failure │ │ Record Retry with result backoffCore Concepts
Section titled “Core Concepts”Events
Section titled “Events”An event represents something that happened in your system — order.created, user.signed_up, payment.failed, etc. Before you can push events, you register their types with Sparrow:
curl -X POST http://localhost:8080/webhook.EventService/RegisterEvent \ -H "Content-Type: application/json" \ -d '{"name": "order.created", "description": "Fires when a new order is placed", "active": true}'Event registrations act as a schema registry. Only registered, active event types can be pushed.
Webhooks
Section titled “Webhooks”A webhook is a registered HTTP endpoint that receives event notifications. When you register a webhook, you provide a URL and optionally a secret for HMAC signature verification:
curl -X POST http://localhost:8080/webhook.WebhookService/RegisterWebhook \ -H "Content-Type: application/json" \ -d '{ "namespace": "default", "url": "https://your-app.com/webhooks", "events": ["order.created"], "active": true, "webhookSecret": "your-secret" }'When you include events during registration, Sparrow automatically creates subscriptions linking that webhook to those event types.
Subscriptions
Section titled “Subscriptions”A subscription connects a webhook to an event type. It controls which events a webhook receives and can optionally transform the payload using Go templates.
Subscriptions are created automatically when you register a webhook with events, but you can also manage them explicitly:
curl -X POST http://localhost:8080/webhook.SubscriptionService/CreateSubscription \ -H "Content-Type: application/json" \ -d '{ "webhookId": "YOUR_WEBHOOK_ID", "eventName": "order.created", "namespace": "default", "active": true }'You can enable payload transforms on a subscription to reshape the event payload before delivery — useful for adapting events to third-party formats like Slack or PagerDuty.
Deliveries
Section titled “Deliveries”A delivery is a single attempt (or series of retry attempts) to send an event payload to a webhook URL. Sparrow tracks every delivery with:
- HTTP status code and response body
- Response time
- Error classification (timeout, DNS, TLS, connection refused, etc.)
- Retry count and next attempt time
Key Design Decisions
Section titled “Key Design Decisions”- Async by default —
PushEventreturns immediately. Processing and delivery happen in background workers via a persistent job queue (River). - At-least-once delivery — retryable failures (server errors, timeouts, connection issues) are automatically retried. Non-retryable failures (DNS errors, TLS errors, 4xx responses) are recorded and not retried.
- Per-webhook health tracking — Sparrow monitors consecutive failures, success rates, and response times for each webhook independently.
- Namespaces — webhooks and events are organized into namespaces for logical separation (e.g.,
billing,notifications). Adefaultnamespace is always available.