Help · section 38 of 44
Events (SSE, Polling, Webhooks)
Mirrors the in-app Help. The live copy in your console and `dlake guide help` are always current.
Row-change events captured per table by a tr_<t>_dl_Event trigger into a platform-managed outbox, consumable three ways:
- Polling —
GET /api/ddl/events/changes?cursor=N&tables=&ops=(cursor-based). - SSE — mint a stream token (
POST /events/stream/token), connect to/events/stream?token=...;Last-Event-IDresume, optionalcoalesce=<ms>batching; default is live-from-now,since=<id>replays history. - Webhooks — see Webhooks.
Permissions:
events.readto consume (all roles),events.manage(Admin) to enable capture per table or manage webhooks. Row-Level Security applies: on RLS-protected tables, insert/update events are delivered only if the consumer’s identity can read the row (SSE/polling: the caller; webhooks: the subscription owner). Delete events always pass (row key only). Suppressed events still advance cursors. Scope-restricted keys: a scoped key’s polling + SSE feed is narrowed to the entities it may read, and a field-restricted key also has each event’s payload column-filtered to its read field policy — excluded columns are stripped fromdata,rowKey, andchangedColumnsbefore delivery (a not-granted primary-key column is stripped fromrowKeytoo; grant it to correlate on it).
SSE frame format — handle BOTH shapes; do NOT key on the event name:
- Live (default after connect): one Server-Sent Event per change —
event: insert|update|delete, anddata:is a single event object:{ "id", "occurredUtc", "schema", "table", "op", "rowKey": {<key columns>}, "data": {<full row, incl. control + dl_ columns>}, "changedColumns": [...], "actor": {...} }. - Replay (connect with
&since=<cursor>): coalesced batches —event: batch, anddata:={ "from": N, "to": M, "count": K, "events": [ <event object>, ... ] }. :heartbeatcomment lines are sent periodically to keep the connection open.
Track the highest event id you see (or to from a batch) and send it as &since= on reconnect for lossless replay. If the server detects a delivery gap it terminates the stream rather than silently skipping events; reconnect with your last &since= and the stream catches up from there before resuming live. Delete events carry rowKey only (no data).