Skip to content

Realtime

Record changes pushed over one WebSocket with the Dart SDK; per-record subscriptions, connection state, pausing.

final sub = vb.collection('posts').subscribe((e) {
switch (e.action) {
case RealtimeAction.create || RealtimeAction.update:
upsert(e.record!);
case RealtimeAction.delete:
remove(e.id);
}
});
await sub.ready; // the server has confirmed; earlier events may be missed
// later
sub.cancel();

Every subscription of a client shares one WebSocket to <baseUrl>/realtime. It opens on the first subscription and closes after the last is cancelled.

vb.collection('posts').subscribe(onEvent, ids: [postId]);
vb.realtime.subscribe('*', onEvent); // every collection
StreamBuilder<RealtimeEvent>(
stream: vb.collection('posts').events(), // subscribes on listen, cancels on cancel
builder: ...,
)

The server checks every event against the subscriber: the collection’s view rule for each record, and its list rule too for a whole-collection subscription. A subscriber only gets records it could read through the API.

The session’s token goes over the connection, and a new one after each refresh or sign-in; signing out reconnects so the old identity is dropped.

vb.realtime.state; // idle, connecting, open, reconnecting, paused
vb.realtime.states; // Stream<RealtimeState>

A dropped connection reconnects with backoff (250 ms up to 10 s) and subscribes again. Events sent while it was down aren’t replayed: reload what matters when the state goes back to open. The backoff starts over only once a connection has stayed up for 5 seconds, and if the server refuses the app’s origin (security.allowed_origins), the client stops reconnecting and goes idle (vaultbase 0.6.0+). sub.ready also completes when the subscription is cancelled or the client is closed, so awaiting it never hangs.

vb.realtime.pause() closes the connection and keeps the subscriptions; resume() reconnects. In Flutter, VaultbaseLifecycle does this when the app goes to the background.