Skip to Content
Client SDKMetadata

Client Metadata

Mesh provides two types of metadata storage: Connection Metadata and Room Metadata. Both are stored in Redis and accessible across all server instances. This page explains how to work with metadata from the client side.

Accessing Connection Metadata

Clients can retrieve connection metadata directly:

const metadata = await client.getConnectionMetadata("conn123"); console.log(metadata.userId, metadata.username);

To fetch metadata for the current connection, use getConnectionMetadata without any arguments:

const metadata = await client.getConnectionMetadata(); console.log(metadata.userId, metadata.username);

Updating Connection Metadata

There’s no built-in way for clients to update metadata directly (for safety), but you can expose a custom command on the server:

// Server-side server.exposeCommand("update-my-metadata", async (ctx) => { const { status } = ctx.payload; const existing = await server.connectionManager.getMetadata(ctx.connection); await server.connectionManager.setMetadata(ctx.connection, { ...existing, status, }); return true; });
// Client-side await client.command("update-my-metadata", { status: "away", });

Accessing Room Metadata

You can also fetch metadata for a specific room:

const meta = await client.getRoomMetadata("lobby"); console.log(meta.topic, meta.maxUsers);

Updating Room Metadata

Room metadata updates must also go through a server-exposed command:

// Server-side server.exposeCommand("update-room-metadata", async (ctx) => { const { roomName, metadata } = ctx.payload; await server.roomManager.updateMetadata(roomName, metadata); return true; });
// Client-side await client.command("update-room-metadata", { roomName: "lobby", metadata: { topic: "New Topic" }, });

Combining Metadata with Presence

Metadata is especially useful alongside presence updates — for example, to show usernames and avatars next to connection events:

const { success, present } = await client.subscribePresence( "lobby", async (update) => { const metadata = await client.getConnectionMetadata(update.connectionId); if (update.type === "join") { addUserToUI(metadata); } else if (update.type === "leave") { removeUserFromUI(metadata.userId); } } ); if (success) { const allMetadata = await Promise.all( present.map((connId) => client.getConnectionMetadata(connId)) ); allMetadata.forEach(addUserToUI); }

Subscribing to Metadata Changes

Mesh doesn’t currently push metadata updates automatically. You can simulate live updates using either channels or records.

Using Channels

// Server-side await server.publishToChannel( `user:${userId}:metadata`, JSON.stringify(updatedMetadata) ); // Client-side await client.subscribeChannel(`user:${userId}:metadata`, (message) => { const meta = JSON.parse(message); updateUserInUI(meta); });

Using Records

// Server-side await server.publishRecordUpdate(`user:${userId}:metadata`, updatedMetadata); // Client-side await client.subscribeRecord(`user:${userId}:metadata`, (update) => { updateUserInUI(update.full); });

Best Practices

  1. Use the built-in getConnectionMetadata and getRoomMetadata when possible
  2. Expose specific server commands for controlled metadata updates
  3. Do not store sensitive data in metadata
  4. Keep metadata compact and fast to serialize
  5. Use records or channels to simulate metadata subscriptions when needed
Last updated on
© 2025