Server: Metadata
Mesh supports two types of metadata:
- Connection metadata — data attached to individual WebSocket connections
- Room metadata — data associated with named rooms
All metadata is stored in Redis and accessible across all server instances.
Connection metadata
Useful for identifying users, storing roles, or tracking per-connection session info.
Set metadata
await server.connectionManager.setMetadata(connection, {
userId: "user123",
role: "admin",
lastActive: Date.now(),
});
Get metadata
One connection
const metadata = await server.connectionManager.getMetadata("conn123");
All connections
Returns an array of { [connectionId]: metadata }
objects:
const all = await server.connectionManager.getAllMetadata();
// [
// { "conn1": { userId: "user123", ... } },
// { "conn2": { userId: "user456", ... } },
// ...
// ]
Filtered connections
You can filter connections based on their metadata using an optional filter function:
const filtered = await server.connectionManager.getAllMetadata(
(connectionId, metadata) => metadata.userId > 100 && metadata.userId < 300
);
// [
// { "conn123": { userId: 123, ... } },
// { "conn234": { userId: 234, ... } },
// ]
This reduces boilerplate when you need to select specific connections based on metadata criteria.
All connections in a room
Also returns an array of { [connectionId]: metadata }
objects:
const members = await server.connectionManager.getAllMetadataForRoom("lobby");
Both methods return an array of objects rather than a single merged object.
Update metadata
Call setMetadata(...)
again to completely replace the previous value:
const existing = await server.connectionManager.getMetadata("conn123");
await server.connectionManager.setMetadata("conn123", {
...existing,
lastActive: Date.now(),
});
Cleanup
Connection metadata is automatically removed when the connection disconnects.
Room metadata
Useful for storing room-level settings, topic info, or ownership metadata.
Set metadata
await server.roomManager.setMetadata("lobby", {
topic: "General",
createdBy: "user123",
maxUsers: 10,
});
This replaces any existing metadata for the room.
Update metadata (partial)
await server.roomManager.updateMetadata("lobby", {
topic: "New Topic",
});
This merges the new fields into the existing record.
Get metadata
One room
const metadata = await server.roomManager.getMetadata("lobby");
All rooms
Returns an object mapping room names to metadata:
const all = await server.roomManager.getAllMetadata();
// {
// "lobby": { topic: "General", ... },
// "dev": { topic: "Dev Chat", ... }
// }
Filtered rooms
You can filter rooms based on their metadata using an optional filter function:
const publicRooms = await server.roomManager.getAllMetadata(
(roomName, metadata) => metadata.type === "public"
);
// {
// "lobby": { type: "public", topic: "General", ... },
// "help": { type: "public", topic: "Support", ... }
// }
This makes it easy to select specific rooms based on metadata criteria.
Delete metadata
await server.roomManager.setMetadata("lobby", null);
Room metadata is also removed automatically if you call server.clearRoom(...)
.
Exposing metadata to clients
You don’t need to define your own commands for basic metadata reads — Mesh provides built-in support.
Connection metadata
// Client
const metadata = await client.getConnectionMetadata("conn123");
The client can request their own metadata by omitting the connection ID:
// Client
const metadata = await client.getConnectionMetadata();
Room metadata
// Client
const metadata = await client.getRoomMetadata("lobby");
Best practices
- Keep metadata small — avoid bloated objects, especially with many connections
- Don’t store sensitive data — metadata may be exposed to clients if not filtered
- Use
updateMetadata
for partial writes — safer and more efficient - Use consistent ID patterns — e.g.
"lobby"
,"dev"
,"user:123"