Database change events
Get told when rows are inserted, updated or deleted: turning change capture on per table, the event format, delivery and ordering, who may listen, and why an event may be missing.
With change capture on, every write to a chosen table publishes an event on the channel db.table.<table>. Use it to refresh a list when data changes, without polling.
Turn it on
Realtime › Database change data capture
Switch it on and pick the tables. Nothing is published for tables you didn't pick.
Allow listeners
Add a rule that lets the right callers
SUBSCRIBEtodb.table.<table>(Policy language (SPL)).Listen
Subscribe like any channel.
sovaria.realtime.channel('db.table.orders', { onMessage: async (event) => { // { event_type: 'row.inserted' | 'row.updated' | 'row.deleted', table, schema, timestamp, event_id, row_count } setOrders(await loadMyOrders()) // re-read through your rules }, })
What an event contains
| Field | Value |
|---|---|
event_type | row.inserted, row.updated or row.deleted |
table, schema | The table that changed (public) |
row_count | How many rows the statement changed |
timestamp | When it was committed |
event_id | Unique per event — use it to ignore a duplicate |
Events say that rows changed, not their contents. Clients then read what they may see through your access policies and row-level security, so a listener never receives rows it couldn't query itself.
Delivery and ordering
- Events are written to a durable outbox before the write returns and delivered from there with retries, so a restart delays them rather than losing them.
- Events for one table arrive in commit order.
- A retried delivery carries the same
event_id; duplicates are dropped by realtime, and your code can ignore any it has already handled. - The same events can also call your HTTPS endpoint — database webhooks (Database webhooks).
An event didn't arrive
| Check | Why |
|---|---|
| Is change capture on for that table? | Only picked tables publish. |
| Did the write happen through Sovaria? | Writes over a direct Postgres connection don't go through the API and aren't published. |
| Did the statement change rows? | An update that matched no rows (for example because of row-level security) publishes nothing. |
| Is the client allowed to subscribe? | A refused subscription closes with 4401/4408. |
| Was the client offline? | Catch up with replay (Channels and connections). |
Something unclear or missing on this page?Tell us