Skip to Content
Presence

Presence

Mesh tracks which connections are currently present in each room (if presence tracking is enabled for the room), and notifies subscribed clients when others join or leave.

Presence—and presence state—is tracked per connection, not per user.

When a user opens your app in multiple tabs or devices, each creates its own WebSocket connection. These connections are treated independently in Mesh, each with its own:

  • Connection ID
  • Room membership
  • Per-room presence status
  • Optional presence state

Even if those connections share the same userId, Mesh does not deduplicate them. This is intentional—Mesh gives you flexible primitives without enforcing identity rules or session merging.

💡

To implement user-level presence (e.g. “only show one typing indicator per user”):

  1. Store a userId in connection metadata
  2. On the client, call getConnectionMetadata(connectionId)
  3. Deduplicate by userId in your UI

For a ready-made solution, use the Unified Presence utility which handles this pattern elegantly.

See Server SDK → Presence for details.


Basic usage

Server: enable presence tracking

// Enable tracking for a single room server.trackPresence("lobby"); // Or for all matching rooms server.trackPresence(/^.+$/);

Client: subscribe to presence

const { success, present } = await client.subscribePresence( "lobby", (update) => { if (update.type === "join") { console.log("Joined:", update.connectionId); } else if (update.type === "leave") { console.log("Left:", update.connectionId); } } );

You’ll get a list of currently present connections and live updates as others join or leave.

Unsubscribe when no longer needed:

await client.unsubscribePresence("lobby");

Presence states

Clients can publish transient status info like "typing", "away", or anything your app defines.

await client.publishPresenceState("lobby", { state: { status: "typing" }, expireAfter: 8000, // optional (ms) });

These states:

  • Are scoped to a specific room + connection
  • Automatically expire (if expireAfter is set)
  • Are cleared when the connection leaves the room or disconnects

Clients subscribed to presence in that room will receive a "state" update:

{ type: "state", connectionId: "abc123", state: { status: "typing" } // or null if cleared/expired }

Summary

Presence is ideal for:

  • Who’s online indicators
  • Live room rosters
  • Typing/activity signals
  • Lightweight awareness in collaborative apps

See Server SDK → Presence and Client SDK → Presence for full APIs and advanced behavior.

Last updated on
© 2025