Skip to Content
Server SDKPresence

Server: Presence

Enable real-time tracking of who’s in a room. Mesh uses Redis TTLs and keyspace notifications to automatically clean up stale entries and notify subscribed clients.

Enable presence tracking

Track individual rooms or patterns:

server.trackPresence("lobby"); server.trackPresence(/^.+$/);

With options

Customize TTL or restrict visibility per connection:

server.trackPresence("admin-room", { ttl: 60_000, // Presence entry expires after 60s of inactivity (default is 0, meaning no expiration) guard: async (conn, roomName) => { const meta = await server.connectionManager.getMetadata(conn); return meta?.isAdmin === true; }, });

How it works

  • Presence entries are stored in Redis with a TTL
  • TTL is refreshed while the connection is alive
  • On disconnect or inactivity, TTL expires
  • Mesh emits a leave event and notifies subscribers
💡

Presence expiration uses Redis keyspace notifications. You can disable this via enablePresenceExpirationEvents: false in your MeshServer config.

This might be desirable if you want to implement a custom cleanup strategy, or if your Redis setup is very high traffic to the point of the overhead of processing keyspace notifications could impact performance. In most cases though, you should leave this enabled.

Get current presence

const ids = await server.presenceManager.getPresentConnections("lobby"); // ["conn123", "conn456"]

Optional: Disable auto-cleanup

const server = new MeshServer({ enablePresenceExpirationEvents: false, });

With this setting, you are responsible for manually cleaning up expired presence entries.

Per-connection model

Presence is tracked per connection, not per user.

If a user opens multiple tabs or devices, each one gets a unique connection ID and separate presence state—even if all share the same userId in metadata.

This gives you precise control and avoids assumptions about identity or sessions.

To group presence by user:

  1. Store userId in connection metadata
  2. Resolve metadata by connectionId on the client with client.getConnectionMetadata(connectionId)
  3. Deduplicate by userId in your UI
💡

This enables user-level presence like “only one typing indicator per user” even with multiple sessions.

Presence state

Clients can publish ephemeral presence states (e.g. "typing", "away").

On the server:

  • State is stored at mesh:presence:state:{room}:{connectionId}
  • It’s removed on disconnect, leave, or expiration
  • States can have TTLs via expireAfter
  • When cleared, Mesh emits { type: "state", state: null } to subscribers

Enrich presence with metadata

server.onConnection(async (conn) => { await server.connectionManager.setMetadata(conn, { userId: "user123", username: "Alice", avatar: "https://example.com/avatar.png", }); });

See Client SDK → Presence for subscribing and handling updates.

Last updated on
© 2025