Realtime
WebSocket + SSE subscriptions for collection events.
vb.subscribe(collection, filter, cb) opens a long-lived realtime
connection and routes server events to your callback. Backed by a
WebSocket where supported, with automatic SSE fallback for environments
that can’t open WS (some serverless platforms, certain corporate
proxies).
Subscribe to all events
Section titled “Subscribe to all events”const off = vb.subscribe("posts", "*", (ev) => { console.log(ev.type, ev.record); // ev.type: "create" | "update" | "delete" // ev.record: T (typed via Schema generic); ev.id on delete});
// later, drop just this subscription:off();Filter to a single record
Section titled “Filter to a single record”vb.subscribe("posts", "p_42", (ev) => { // only fires for record id = "p_42"});Pass an array to follow several records: vb.subscribe("posts", ["p_1", "p_2"], cb).
What you receive
Section titled “What you receive”The server checks every event against your auth before sending it: the
collection’s view_rule for each record, and its list_rule too when you
subscribe to the whole collection ("*"). So a subscriber only gets
records they could read through the API; filter further in your callback.
A singleton has no list, so its
updates follow the view_rule alone, whichever way you subscribe (server
0.26.2+; older servers only sent vb.subscribe("site", "*") events to admins, so
subscribe to the record’s id there).
Every event is delivered, however close together: three quick updates to a record are three callbacks. (SDK 0.7.1 and older dropped a second event for the same record and type within a second.)
Multiple subscriptions
Section titled “Multiple subscriptions”const offPosts = vb.subscribe("posts", "*", onPost);const offUsers = vb.subscribe("users", "*", onUser);
// Disconnect the realtime channel entirely (keeps auth):vb.closeRealtime();A single WS connection is shared across all vb.subscribe calls — the
manager multiplexes topic subscriptions over the same socket. Each callback
gets only its own collection’s events. To hear every collection, subscribe to
"*": vb.subscribe("*", "*", cb), and switch on ev.collection.
Auth + reconnect
Section titled “Auth + reconnect”The connection authenticates with the token in vb.client.authStore, and
follows it:
- When the token changes (a refresh, a new sign-in), the SDK sends the new one over the open connection. Signing out closes the connection so it reconnects as anonymous.
- The server re-checks a connection’s token every minute (server 0.17+).
If it no longer holds, the server sends
auth_expiredand treats the connection as anonymous; the SDK then refreshes once and re-authenticates. If the refresh fails, events that need auth stop arriving until the user signs in again. - A dropped connection reconnects with backoff and re-subscribes every topic.
Backoff: 250 ms, 500 ms, 1 s, 2 s, 5 s, then every 10 s, each ±20%. Reconnect
retries forever; stop it with vb.closeRealtime().
SSE fallback
Section titled “SSE fallback”If the WebSocket can’t open (an error, or no open within 5 s) and the
runtime has EventSource (browsers; Bun and Node don’t), the SDK falls back to
server-sent events at GET /api/v1/realtime + POST /api/v1/realtime
for subscription updates. A dropped SSE stream reconnects with the same
backoff (SDK 0.7.3+). The same subscribe API works either way —
your code doesn’t change.
Topic shape
Section titled “Topic shape”Each event is what your callback receives:
{ "type": "create", "collection": "posts", "record": { "id": "p_42", "title": "hi" } }{ "type": "delete", "collection": "posts", "id": "p_42" }A record in an event has no expand. To show related records, fetch the record
again with vb.collection(name).get(id, { expand }). See
Realtime concept for the full wire format.
Caveats
Section titled “Caveats”- A single server (read worker threads are on by default) delivers every
event to every subscriber, and so do several servers sharing one
Postgres database. Only the deprecated
vaultbase clusterkeeps subscriptions per worker; don’t use it with realtime. - There is no durable replay: events sent while the connection was down are not delivered after it reconnects. Refetch what you show after a reconnect.
- Rules are evaluated server-side per event; rules that are expensive to evaluate cost CPU on the broadcast path.