TypeScript realtime
Connect, subscribe, consume ordered durable events, and recover safely after gaps or reconnects.
Connect and subscribe
const connection = await appUser.realtime.connect({
webSocketFactory: (url, protocols) =>
new WebSocket(url, [...protocols]),
});
const subscription = await connection.channels.subscribe({
channelTypeKey: 'messaging',
channelId: 'support-123',
});
const stop = subscription.onEvent((event) => {
renderChannelEvent(event);
});
stop();
connection.close();The connection obtains a one-use ticket, negotiates only vchat.realtime.v1, and is ready only after the strict connection.ready envelope. The subscription is authorized independently and starts from the server-acknowledged event baseline.
Delivery and sequence
- Delivery is at-least-once. Deduplicate by eventId.
- Track subscription.lastEventSequence for the accepted channel position.
- The SDK bounds in-memory deduplication; it does not persist exactly-once state.
- A refresh_required or stale subscription requires authoritative REST refresh before local continuity can be trusted.
- Compatible unknown future v1 event names are ignored safely while known ordering gaps trigger recovery.
Private user state
const stopPrivate = connection.onUserMessagingState((update) => {
if (update.conversation.changed) {
renderConversation(update.conversation.value);
}
if (update.unreadSummary.changed) {
renderUnread(update.unreadSummary.value);
}
});Private conversation, unread, and thread state is visible only to the authenticated app user and uses independent version fences.
Presence and typing
An active channel subscription exposes connection-local presence and typing controllers. Presence watches exact bounded user IDs. Typing is scoped to the channel or a one-depth thread. Both are ephemeral and cleared on disconnect; neither is persisted or replayed as durable history.