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.

Connection Metadata

Accessing Connection Metadata

Clients can retrieve connection metadata for any connection by providing the connection ID:

const = await .("conn123"); .(.userId, .username);

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

const = await .(); .(.userId, .username);

Setting Connection Metadata

Clients can directly set metadata for their own connection using the built-in setConnectionMetadata method:

// Replace entire metadata (default behavior) await .({ : "online", : { : "dark" } });

Update Strategies

The setConnectionMetadata method supports three different update strategies:

Replace Strategy (default):

// Replaces the entire metadata object await .( { : "away" }, { : "replace" } );

Merge Strategy:

// Merges with existing metadata at the top level await .( { : "away" }, { : "merge" } ); // Existing: { user: "john", preferences: { theme: "dark" } } // Result: { user: "john", status: "away", preferences: { theme: "dark" } }

Deep Merge Strategy:

// Recursively merges nested objects await .( { : { : false } }, { : "deepMerge" } ); // Existing: { user: "john", preferences: { theme: "dark", lang: "en" } } // Result: { user: "john", preferences: { theme: "dark", lang: "en", notifications: false } }

Server-Controlled Metadata Pattern

For scenarios requiring server validation, you can still use custom commands:

// Server-side .("update-user-status", async () => { const { } = .; // Server validation logic here if (!["online", "away", "busy"].()) { throw new ("Invalid status"); } // Use merge strategy to preserve other metadata await ..(., { , : .() }, { : "merge" } ); return { : true }; });
// Client-side await .("update-user-status", { : "away" });

Room Metadata

Accessing Room Metadata

You can fetch metadata for any room:

const = await .("lobby"); .(.topic, .maxUsers);

Setting Room Metadata

Room metadata can only be set server-side. Use custom commands to expose controlled updates.

The server-side room metadata API supports the same strategies as connection metadata:

// Server-side .("update-room-topic", async () => { const { , } = .; // Validate permissions here if (!await isRoomModerator(., )) { throw new ("Insufficient permissions"); } await ..(, { , : .() }, { : "merge" }); return { : true }; });
// Client-side await .("update-room-topic", { : "lobby", : "Welcome to the lobby!" });

Metadata with Presence

Metadata is especially powerful when combined with presence updates. Here’s how to show user information alongside presence events:

const { , } = await .( "lobby", async () => { const = await .(.); if (. === "join") { .(`${.username} joined the room`); addUserToUI(); } else if (. === "leave") { .(`${.username} left the room`); removeUserFromUI(.userId); } } ); // Load initial user list with metadata if () { const = await .( .(() => .()) ); .(addUserToUI); }

Metadata Change Notifications

Mesh doesn’t automatically push metadata updates to clients. If you need live metadata updates, implement them using channels or records:

Using Channels

// Server-side: Notify when user metadata changes .("update-user-metadata", async () => { const { } = .; // Update the metadata await ..(., , { : "merge" }); // Broadcast the change const = await ..(..); for (const of ) { await .( `room:${}:metadata-updates`, .({ : .., : await ..(.) }) ); } return { : true }; }); // Client-side: Listen for metadata changes await .("room:lobby:metadata-updates", () => { const { , } = .(); updateUserInUI(, ); });

Using Records

// Server-side: Store user metadata as a record .("update-user-metadata", async () => { const { } = .; // Update both connection metadata and a record await ..(., , { : "merge" }); await .( `user:${..}:metadata`, , { : "merge" } ); return { : true }; }); // Client-side: Subscribe to metadata record await .("user:conn123:metadata", () => { updateUserInUI("conn123", .); });

Best Practices

  1. Use descriptive metadata structure:

    const metadata = { user: { id: "123", username: "john", avatar: "/avatars/john.png" }, session: { status: "online", lastSeen: Date.now() }, preferences: { theme: "dark", lang: "en" } };
  2. Leverage merge strategies for partial updates:

    // Client can safely update status without affecting user info await client.setConnectionMetadata( { session: { status: "away" } }, { strategy: "deepMerge" } );
  3. Keep metadata compact and serializable - Avoid large objects or functions

  4. Use metadata for UI state, not application logic - Critical data should be stored in your database

  5. Consider metadata lifecycle - Connection metadata is automatically cleaned up when connections close

Last updated on
© 2025