Skip to main content

Realtime, CDC, presence, and durable topics

All realtime endpoints are WebSockets. Authenticate with a bearer header, x-api-key, or api_key query parameter. Browser clients normally use the query parameter; server clients should prefer headers.

Choose a stream​

EndpointSemanticsRecovery
/v1/stream?table=messagesOne committed change record per writefrom or from_sequence replay while retained
/v1/query-stream?table=messagesSnapshot followed by current query updatesSends a fresh snapshot if a consumer lags
/v1/broadcast/{channel}Ephemeral fanoutNo history; use topics for replay
/v1/presence/{channel}/streamSnapshot plus join/leave stateFresh state snapshot on lag
/v1/topics/{partition}/streamOrdered persisted messagesCursor replay; cursor_expired when retention is gone
/realtime/v1/websocketSupabase/Phoenix channel protocolProtocol-level join and presence behavior

Change feed​

wss://db.example.com/v1/stream?table=messages&api_key=...&from_sequence=42

Frames contain tenant, database, branch, table, operation, primary key, before/after bytes, commit timestamp, transaction id, and sequence:

{
"tenant": "default",
"database": "default",
"branch": "main",
"table": "messages",
"op": "INSERT",
"pk": [109, 45, 49],
"before": null,
"after": [104, 105],
"commit_ts": 7,
"tx_id": 7,
"sequence": 42
}

pk, before, and after are byte arrays. The stream replays retained changes oldest-first and suppresses already delivered sequence numbers. If a cursor has expired, the server sends an error and closes instead of silently returning an incomplete history; resnapshot and reconnect.

Reactive queries​

wss://db.example.com/v1/query-stream?table=messages&limit=100&select=id,body&order=id.desc&status=eq.ready

The first frame is a snapshot; subsequent frames are update messages. Filters, projections, order, views, and branch selection are reevaluated on committed changes. Lagging consumers receive a current snapshot.

Broadcast and presence​

Publish an ephemeral event:

curl -fsS -X POST \
-H 'Authorization: Bearer local-dev-key' \
-H 'Content-Type: application/json' \
--data '{"channel":"lobby","payload":{"event":"typing","user":"ada"}}' \
http://127.0.0.1:8080/v1/broadcast

Broadcast is tenant-scoped and intentionally not WAL-backed. Presence rooms start with a state snapshot, then emit joins/leaves. Members have a TTL, rooms cap at 1,000 members, and abandoned state is swept.

Durable topics​

rymedb-cli topics append chat-room m-1 '{"text":"hello"}'
rymedb-cli topics read chat-room --from 0
rymedb-cli stream broadcast lobby --count 1

POST /v1/topics/append atomically persists a partition message and cursor. The topic stream replays from from=<cursor> and then follows live appends, including all retained pages when the backlog exceeds 1,000 messages. Use it for chat delivery, agent jobs, or game events that must survive a disconnect. Retention is bounded; handle cursor_expired by taking a new application snapshot. REST reads return a conflict for an expired cursor, while WebSocket streams send cursor_expired. A cursor ahead of the current topic tail is rejected as cursor_ahead (or an invalid cursor for REST); retry from the last cursor returned by the server.

Supabase Realtime​

/realtime/v1/websocket?apikey=<key>&vsn=1.0.0 accepts Phoenix-style phx_join, phx_leave, heartbeat, broadcast, presence, and postgres_changes configuration. RLS is checked before database changes are exposed. Each connection is bounded to 64 channels and 32 database-change subscriptions per channel; incoming frames are limited to 1 MiB and broadcast payloads to 64 KiB. The npm/TypeScript and Rust SDKs wrap this protocol.

Delivery rules​

  • CDC is emitted once after a committed write; SQL, REST, native, gRPC, and RESP writes share the history.
  • Change history and outgoing queues are bounded.
  • Heartbeats detect dead connections; stalled sends are disconnected after a bounded timeout.
  • Broadcast is best-effort and ephemeral; query streams resnapshot; durable topics replay within retention.
  • Tenant, branch, and QoS limits apply to sockets and delivered bytes.