How-to guide
Trigger Queuey from Supabase database webhooks
A Supabase Database Webhook fires an HTTP request whenever a row changes. Point it at your Queuey ingress URL and every insert, update or delete becomes a durable event — with retries, a dead-letter queue, ordering and full delivery history — before it reaches whatever should react to it. No SDK, no code: connect the project from the console and Queuey installs the webhook for you — or set it up by hand with one URL and one header.
Connect automatically (recommended)
The console can install the webhook for you. Open Integrations in the Queuey console, click Connect on Supabase, and approve the access request on supabase.com (it is an organization-level grant — pick the organization that owns the project). Then choose a workspace, a project and one or more tables, tick the operations you want (insert, update, delete), and click Create queue & install trigger. For each table Queuey:
- creates a queue named after the table (
ordersforpublic.orders) that requires an API key — a request without it is refused with401; - mints a key that can publish to that one queue only, so a leaked trigger header cannot reach anything else you own;
- installs a Database Webhook trigger named
queuey_<table>in your project — visible under Integrations → Database Webhooks like any hook you made by hand, with a 5-second timeout; - labels every event with the operation (
INSERT,UPDATE,DELETE) read from the body, so the console and your delivery rules can tell them apart.
The queue starts in Log-only: change a row, watch it arrive, then set a destination under the queue’s Delivery settings when you are ready. Supabase itself does not retry the request it sends to Queuey; everything after the 202 is durable. Bodies above roughly 64 KB are not sent by Supabase’s pg_net at all — keep wide rows out of webhook tables or send ids and let the receiver fetch.
401 — and you drop the queuey_* triggers yourself. Queuey never stores your database credentials: the grant is an OAuth token, encrypted at rest, used only to list your projects and tables, run the trigger SQL, and check that the trigger still exists.Or by hand: 1 — Create the webhook
Prefer to keep Queuey out of your Supabase organization? The manual route is one URL and one header. In the Supabase dashboard, open Integrations → Database Webhooks (the first time, click Install integration — it enables the pg_net extension), then Create a new hook:
Name: orders-to-queuey
Table: public.orders
Events: Insert, Update, Delete
Type: HTTP Request
Method: POST
URL: https://ingress.queuey.ai/events/ten_yourTenant/orders
Headers: Content-Type: application/json
X-Api-Key: qak_8fK2mNpQ.aB3dE7gH9jK1mN4pR6tV8wX0yZThe URL and the X-Api-Key value come from your Queuey console — see the quickstart if you have neither yet. That is the whole integration: Supabase delivers the row change to Queuey, and Queuey answers 202 Accepted once the event is durably stored.
2 — What arrives on the queue
Supabase sends a fixed JSON shape: the operation, the table, and the row (old_record is filled on updates and deletes). Queuey accepts it as-is — no envelope required:
{
"type": "INSERT",
"table": "orders",
"schema": "public",
"record": {
"id": 1042,
"customer_id": "ACME",
"status": "placed",
"created_at": "2026-08-31T14:38:36.69Z"
},
"old_record": null
}HTTP/1.1 202 Accepted
Content-Type: application/json
{
"queuePublicId": "que_Rp2yPELnp4sr",
"eventId": "evt_nd9qgy1sjPIW",
"receivedAtUtc": "2026-08-31T14:38:36.71Z",
"mode": "Deliver",
"replayed": false
}From here the event behaves like any other Queuey event: it shows up in the console, delivers to the queue’s target with the queue’s retry policy, and lands in the dead-letter queue instead of disappearing when the target will not take it.
"mode": "LogOnly". To deliver, open the queue in the console, set its endpoint under Delivery, and switch the queue to Deliver. Events accepted while the queue was log-only stay inspectable in the console.3 — Telling operations apart
The operation travels in the body: type says whether the row was inserted, updated or deleted, and table says where. Your receiver branches on those two fields. When different tables deserve different handling — separate targets, separate retry policies, separate ordering — give each table its own webhook pointing at its own queue (orders, invoices, …) rather than parsing everything out of one stream.
Idempotency-Key header on the webhook would carry the same value on every row change — and Queuey would correctly deduplicate all but the first event away. Leave it unset. Supabase’s delivery can occasionally duplicate a request; make the final receiver idempotent instead (reliable delivery) — a duplicate you can ignore beats a row change you never heard about.Prefer SQL? The webhook is a trigger
Dashboard webhooks are ordinary Postgres triggers under the hood. If you keep your schema in migrations — or you are letting an AI agent set the project up — create the trigger directly:
-- The dashboard webhook is just a trigger. Creating it in SQL means it
-- lives in your migrations and survives a project rebuild.
create trigger orders_to_queuey
after insert on public.orders
for each row
execute function supabase_functions.http_request(
'https://ingress.queuey.ai/events/ten_yourTenant/orders',
'POST',
'{"Content-Type":"application/json","X-Api-Key":"qak_…"}',
'{}',
'5000' -- timeout in ms; the 202 ack is fast, but do not go lower
);Why not point Supabase straight at your receiver?
You can — and it works until the receiver has a bad minute. Database Webhooks are sent via pg_net: fire-and-forget, with a short timeout, no durable retry, no dead-letter queue, and no way to see afterwards what was sent or what failed. If your endpoint is down, deploying, or rate-limited, that row change is simply gone. Putting Queuey’s ingress in between turns the fragile hop into the shortest one — a fast 202 from an endpoint built to say yes — and every hop after that is retried, observable and replayable.
Related
- Deliver to a BuildShip workflow — the natural next hop: Supabase → Queuey → BuildShip.
- Reliable delivery — retries, idempotency and the dead-letter queue.
- Ordering & per-key lanes — keep changes to the same row in order.