1. Home
  2. Destinations
  3. Webhooks
DESTINATION · HTTP

Webhooks for your Postgres database.

Every committed insert, update and delete POSTed to an endpoint you own — signed, batched, retried, and in order per row. No triggers, no polling, no queue to run.

The webhook sink is the simplest way to react to database changes from any language: Waltail reads your database's write-ahead log over logical replication and POSTs each batch of changes as JSON to a URL. Your handler verifies the signature, processes the messages, and returns a 2xx.

Because the payload is plain JSON over HTTPS, the same sink reaches serverless functions, internal services, Slack and Discord incoming webhooks, workflow tools, and anything else that accepts a POST.

How delivery works

AspectBehaviour for Webhooks
RequestOne POST per batch, Content-Type: application/json, body {"messages": […]} with each change as an element in commit order.
HeadersX-Pgcdc-Event: changes; with a secret, X-Pgcdc-Signature = hex HMAC-SHA256 of the exact body.
BatchingUp to the sink's batch size per request (default 100). Set it to 1 for one request per change.
OrderingChanges to the same row never overlap; array order inside a batch is commit order.
IdempotencyEach message carries a unique idempotency_key; store it to make your handler safe under redelivery.
On failureAny 2xx is accepted. A 429 pauses the sink for the Retry-After period (30 s if absent) without spending a retry or metering egress. A failed request is retried up to 5 times with exponential backoff (30 s, 1, 2, 4 min, with jitter). After the fifth failure the message is parked as undelivered, the console shows it with the last error, and one click replays it — later changes to the same row wait behind it so order is preserved.
Connection checkBefore the sink is saved, Waltail POSTs {"type":"pgcdc.check"} with X-Pgcdc-Event: check and expects a 2xx within 10 s.

Set up in three steps

  1. Connect your database

    Paste a connection string and press Test. Waltail checks the version (12+), that wal_level is logical, that the user may replicate, and that a slot is free — and shows the fix for anything that fails. Then it creates its own publication and replication slot. Connection guide →

  2. Add Webhooks as a destination

    Pick the tables to stream, choose Webhooks, and fill in Webhook URL. Press Test — Waltail checks it can reach and write to Webhooks before anything is saved.

  3. Change a row

    Insert or update a row. The console shows the first event as it is captured and delivered; from then on, every committed change follows within about a second. Have rows that already exist? Run a backfill — confirm the estimate and they arrive through Webhooks as read events.

Configuration

Fields as the console asks for them. Secrets are encrypted at rest and never shown again.

FieldConsole labelRequiredNotes
urlWebhook URLYesMust start with http:// or https://.
secretSigning secretOptionalWhen set, every request carries an HMAC-SHA256 signature of the body.

Every sink also has two tuning settings: batch size (messages per request, default 100) and rate limit (messages per second, default unlimited). Changes to one row are never in flight twice at once.

Example

What Webhooks receives:

POST /hooks/waltail HTTP/1.1
Content-Type: application/json
X-Pgcdc-Event: changes
X-Pgcdc-Signature: 3f9a…c2e1

{"messages":[{ "op": "update", "table": "public.orders", "data": { "id": 42, "status": "shipped", "total": 19.99 }, "old":  { "id": 42, "status": "paid",    "total": 19.99 }, "seq": 137, "idempotency_key": "9f1c3d2e-6b4a-4c7e-9d0f-2a1b3c4d5e6f", "commit_lsn": "0/1A2B3C8" }]}

Message format reference →

Questions

How do I verify the webhook signature?

Compute HMAC-SHA256 over the raw request body with your signing secret and compare it, constant-time, to the hex value in X-Pgcdc-Signature. Compute it over the bytes you received, before any JSON parsing.

What happens if my endpoint is down?

Waltail keeps the changes and retries with backoff for about 15 minutes, then parks them as undelivered. Nothing is lost on your database side — the change was acknowledged to Postgres only after it was stored. When the endpoint is back, replay everything undelivered in one click.

Can I receive one change per request?

Yes. Set the sink's batch size to 1. Larger batches are cheaper and faster for most consumers.

Can I send to Slack, Discord or a workflow tool?

Any service that accepts a JSON POST works. For services that expect their own body shape, put a small function or worker in between, or use a queue sink and shape the message there.

Related

Cloudflare Queues

Workers consumers

Amazon SQS

Standard and FIFO queues

Amazon EventBridge

Rules, targets, event buses

Use cases: Webhooks for your database · Cache invalidation · Search index sync · Event-driven services · Audit log and archive.

Start streaming to Webhooks.