Skip to content

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.

CapabilityRoomChannel
Publish eventsYesYes
Broadcast eventsYesYes
Message historyYesYes
MembersYesNo
PresenceYesNo
MetadataYesNo
SnapshotsYesNo
CRDT and Yjs helpersUse crdtRoom()No
Lifecycle and destroyYesYes

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.
Terminal window
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",
},
})

Use metadata for shared room settings:

Terminal window
await live.room("project_123").metadata({
metadata: {
title: "Launch plan",
mode: "planning",
locked: false,
},
})

Metadata is returned with the room identity and update time:

Terminal window
const result = await room.metadata({
metadata: {
title: "Launch plan",
},
})

Use an idempotency key when a client may retry a request:

Terminal window
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 are best for streams that users subscribe to or poll:

  • Deployment events.
  • Build status changes.
  • Admin notifications.
  • Live metrics updates.
  • Public activity feeds.
Terminal window
const deployments = live.channel("deployments")
await deployments.broadcast({
type: "deployment.finished",
data: {
deploymentId: "dep_123",
status: "success",
},
})

Channels expose publish, broadcast, history, and stats.

Terminal window
const history = await live.channel("deployments").history({
limit: 50,
cursor,
})

Use history when dashboards reconnect and need to catch up on missed events.

Use stable names that match your product model:

Terminal window
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.

Terminal window
const stats = await live.stats()

Stats return counts for rooms, active members, and messages for the Realtime instance.

Terminal window
await live.room("project_123").destroy()

Use destroy() for closed meetings, deleted documents, finished game lobbies, and temporary rooms.