Postgres changes into Cloudflare Queues.
Feed Workers from your database without polling — batches of changes land in the queue through the Cloudflare API.
The Cloudflare Queues sink sends changes through the Queues REST API in batches of up to 100. Each queue message body carries the change JSON plus the idempotency and ordering keys, so a Worker consumer reads msg.body.payload and can dedupe or order on the keys.
How delivery works
| Aspect | Behaviour for Cloudflare Queues |
|---|---|
| Message | Body = {"payload": <change JSON>, "idempotency_key": "…", "ordering_key": "…"}. |
| Batching | POST …/messages/batch in chunks of 100 (the API maximum). |
| Ordering | Queues are not strictly ordered; use ordering_key and the change's seq to sequence in the consumer. |
| Idempotency | Dedupe on idempotency_key in the body. |
| On failure | Non-2xx or an API-level success: false fails the batch. Any 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 check | GET on the queue through the API — token, account and queue. |
Set up in three steps
-
Connect your database
Paste a connection string and press Test. Waltail checks the version (12+), that
wal_levelislogical, 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 → -
Add Cloudflare Queues as a destination
Pick the tables to stream, choose Cloudflare Queues, and fill in Account ID, Queue ID, API token. Press Test — Waltail checks it can reach and write to Cloudflare Queues before anything is saved.
-
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 Cloudflare Queues as
readevents.
Configuration
Fields as the console asks for them. Secrets are encrypted at rest and never shown again.
| Field | Console label | Required | Notes |
|---|---|---|---|
account_id | Account ID | Yes | |
queue_id | Queue ID | Yes | |
api_token | API token | Yes | Needs the Queues Edit permission. |
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 Cloudflare Queues receives:
export default {
async queue(batch, env) {
for (const msg of batch.messages) {
const { payload, idempotency_key } = msg.body;
// payload.op, payload.table, payload.data …
msg.ack();
}
},
};
Questions
How does the Worker read the change?
The change JSON is msg.body.payload; the keys sit beside it in msg.body.
Which token permission is needed?
An API token with Queues Edit on the account.