Rooms and channels
Rooms and channels are the two primary Realtime surfaces.
Use a room when users join a named space and you care about membership, presence, metadata, snapshots, or collaborative state. Use a channel when you need a broadcast stream with history and stats.
Quick comparison
Section titled “Quick comparison”| Capability | Room | Channel |
|---|---|---|
| Publish events | Yes | Yes |
| Broadcast events | Yes | Yes |
| Message history | Yes | Yes |
| Members | Yes | No |
| Presence | Yes | No |
| Metadata | Yes | No |
| Snapshots | Yes | No |
| CRDT and Yjs helpers | Use crdtRoom() | No |
| Lifecycle and destroy | Yes | Yes |
Rooms are best for product spaces that have members:
- Chat rooms.
- Project activity spaces.
- Video meeting side channels.
- Multiplayer game lobbies.
- Collaborative documents.
- Tenant admin dashboards.
const room = live.room("project_123")
await room.join({ metadata: { role: "editor", }, presence: { status: "online", },})
await room.publish({ type: "task.created", data: { taskId: "task_123", },})Room metadata
Section titled “Room metadata”Use metadata for shared room settings:
await live.room("project_123").metadata({ metadata: { title: "Launch plan", mode: "planning", locked: false, },})Metadata is returned with the room identity and update time:
const result = await room.metadata({ metadata: { title: "Launch plan", },})Publish with idempotency
Section titled “Publish with idempotency”Use an idempotency key when a client may retry a request:
await live.room("project_123").publish({ type: "comment.created", data: { commentId: "comment_123", body: "Looks good.", }, idempotencyKey: "client_event_123",})This keeps client retries from creating duplicate stored messages.
Channels
Section titled “Channels”Channels are best for streams that users subscribe to or poll:
- Deployment events.
- Build status changes.
- Admin notifications.
- Live metrics updates.
- Public activity feeds.
const deployments = live.channel("deployments")
await deployments.broadcast({ type: "deployment.finished", data: { deploymentId: "dep_123", status: "success", },})Channels expose publish, broadcast, history, and stats.
Channel history
Section titled “Channel history”const history = await live.channel("deployments").history({ limit: 50, cursor,})Use history when dashboards reconnect and need to catch up on missed events.
Naming rooms and channels
Section titled “Naming rooms and channels”Use stable names that match your product model:
live.room(`project_${projectId}`)live.room(`tenant_${tenantId}:support`)live.channel("deployments")live.channel(`tenant_${tenantId}:alerts`)Keep names deterministic so every route handler and background job can address the same room or channel.
Read stats
Section titled “Read stats”const stats = await live.stats()Stats return counts for rooms, active members, and messages for the Realtime instance.
Close a room
Section titled “Close a room”await live.room("project_123").destroy()Use destroy() for closed meetings, deleted documents, finished game lobbies,
and temporary rooms.