Skip to Content
Server SDKChannels

Server: Channels

Let clients subscribe to Redis pub/sub channels over WebSocket. Useful for chat, notifications, dashboards, and more.

Expose channels

Clients can only subscribe to channels you’ve explicitly exposed:

// Exact match server.exposeChannel("notifications:global"); // Pattern match server.exposeChannel(/^chat:.+$/); // With a guard server.exposeChannel(/^private:chat:.+$/, async (conn, channel) => { const meta = await server.connectionManager.getMetadata(conn); return meta?.isPremium === true; });

Guards run per-subscription and can block or allow access.

Publish messages

Use publishToChannel(...) to broadcast a message:

await server.publishToChannel( "chat:room1", JSON.stringify({ type: "message", userId: "123", text: "Hello!", }) );

Optional message history

You can store recent messages in Redis by passing a third argument:

await server.publishToChannel( "chat:room1", JSON.stringify({ type: "message", userId: "123", text: "Hello!", }), 50 ); // Keep last 50 messages

These are stored under "mesh:history:<channel>" and sent to clients that request historyLimit.

Persistent message storage

For long-term message storage beyond Redis’s in-memory history, you can enable persistence for channels:

// Enable persistence for all chat channels server.enablePersistenceForChannels(/^chat:.+$/); // Enable persistence with custom options server.enablePersistenceForChannels("notifications:global", { historyLimit: 1000, maxMessageSize: 20480, // 20KB flushInterval: 1000, // 1 second });

Persistence stores messages in a durable backend (SQLite by default) and can be configured with these options:

  • historyLimit: Maximum number of messages to retain per channel (default: 50)
  • maxMessageSize: Maximum message size allowed in bytes (default: 10240 - 10KB)
  • flushInterval: How often to flush buffered messages to storage in ms (default: 500)
  • maxBufferSize: Maximum messages to buffer before forcing a flush (default: 100)
  • filter: Function to determine which messages to persist (default: all messages)
  • adapter: Custom persistence adapter (default: SQLite)

When persistence is enabled, messages published to matching channels are automatically stored and can be retrieved later, even after server restarts.

This lets you selectively persist data for channels where message history matters—like support conversations, audit logs, or direct messaging—without storing transient or high-frequency messages such as notification pings, system heartbeats, or ephemeral alerts.

💡

By default, the persistence layer uses SQLite with an in-memory database (:memory:), which means data is lost when the server restarts.

Configuring persistence storage

To ensure your channel messages truly persist across server restarts, configure a file-based database in your server options:

import { MeshServer } from "@meshsdk/core"; const server = new MeshServer({ port: 3000, redisOptions: { /* your Redis options */ }, persistenceOptions: { filename: "./data/channels.db", }, }); server.enablePersistenceForChannels(/^chat:.+$/);

Relationship between Redis history and persistence

Redis history (via the third parameter to publishToChannel) and persistence (via enablePersistenceForChannels) operate independently but complement each other:

// Enable persistence with a 1000 message limit server.enablePersistenceForChannels("chat:room1", { historyLimit: 1000 }); // Publish with a 50 message Redis history await server.publishToChannel("chat:room1", message, 50);

In this example:

  1. The message is stored in Redis with a 50 message limit (for immediate history)
  2. The same message is also stored in the persistence database with a 1000 message limit (for long-term storage)

When clients request history:

  • Requests with only historyLimit get messages from Redis (fast, recent messages)
  • Requests with both historyLimit and since parameter try to get messages from the persistence layer first, falling back to Redis if needed

This dual-storage approach provides both fast access to recent messages (Redis) and longer-term storage that survives restarts (persistence layer).

Notes

  • Messages must be strings — serialize objects with JSON.stringify(...)
  • Use colons (:) in channel names for structure (e.g. "chat:room:123"). This is just a convention—Mesh doesn’t require or enforce it, but it helps keep things organized when matching with regex.

Use cases

  • Chat — public or private channels, typing indicators
  • Notifications — global alerts, user-specific updates
  • Dashboards — live system metrics, stock tickers
  • Broadcasts — server-to-client or cross-instance messaging

Tips

  • Define consistent message shapes (e.g. { type, userId, timestamp, ... })
  • Use guards to control who can subscribe
  • Use history sparingly and cap it to reasonable sizes
  • For important data that needs to survive restarts, enable persistence
  • Consider using different persistence settings for different channel types
  • Use the filter option to selectively persist only important messages
Last updated on
© 2025