PubSub - Javascript
PubSub is a concise acronym for the Publish-Subscribe mechanism. This mechanism is employed to send and receive messages within a specified topic. As the name implies, to send a message, one must specify the topic and the message to be published. Similarly, to receive a message, a subscriber must be connected to that particular topic.
Here is a visual to better understand the publish-subscribe mechanism.

To utilize PubSub in a meeting, VideoSDK provides a property called pubSub. This enables you to subscribe to any topic and publish to any topic, facilitating the exchange of messages and instructions seamlessly during the meeting.
publish()
- This method is used for publishing a message for a specific topic.
- It can be accessed from the
pubSubproperty by specifying thetopicfor whichpublish()will be used. - It will accept following parameters as input:
message: This parameter represents the actual message to be published and should be inStringformat.options: This object specifies the options for publishing. You can set following properties :persist: When set to true, this option retains the message for the duration of the session. If persist is true, the message will be available for upcoming participants and can be accessed in the VideoSDK Session Dashboard in CSV format after the session is completed.sendOnly: If you want to send a message to specific participants, you can pass their respectiveparticipantIdin the form ofArray<String>here. If you don't provide any IDs, the message will be sent to all participants by default.
payload: If you need to include additional information along with a message, you can pass it here as anobject.
let meeting;
// Initialize Meeting
meeting = VideoSDK.initMeeting({
// ...
});
const topic = "CHAT";
const publishChat = (message) => {
//
try {
await meeting?.pubSub.publish(topic, message, { persist: true });
} catch (e) {
console.log("Error while sending message through pubsub", e);
}
};
publishChat("Hello world!");
subscribe()
- This method serves a dual purpose. Firstly, it is employed to retrieve all previously sent messages associated with a particular
topic. Additionally, it can be used to subscribe to a particulartopic. - By providing the topic to be subscribed to and a listeners object, it ensures that all future messages related to the subscribed topic are received and processed when they arrive.
meeting.pubSub.subscribe(topic, listeners, options?)accepts a listeners object and an optional options object. It returnsPromise<void>. All messages — realtime and old — are delivered exclusively through the listener callbacks; nothing is returned from the awaited call.- It will accept following parameters as input:
topic: The topic to be subscribed to.listeners: An object containing listener callbacks:-
onMessageReceived(message)— Called for every realtime message as soon as it is received.- Use this when: You want to handle each message individually, such as appending it to a chat, triggering a notification, or updating message-specific state.
- Don't use this when: The topic is high-throughput / large-scale (busy chats, live reactions, cursor positions). Firing once per message causes excessive re-renders and state updates — use
onBatchReceivedinstead.
-
onBatchReceived(messages)— Called with an array of realtime messages. These are the same messages delivered throughonMessageReceived, but grouped into a single batch.- Use this when: Processing messages in bulk is more efficient, such as performing a single state update or rendering a large list of messages.
-
onOldMessagesReceived(messages, { isLast })— Called with persisted history in batches — fires once per batch until history is fully delivered. Only messages published withpersist: trueare delivered here.isLastistrueon the final batch.- Use this when: Loading chat history or restoring previously sent messages when a participant joins the meeting.
-
onMessageDrop(info)— Called when incoming realtime messages cannot be delivered. This can happen:- because the client cannot keep up with the incoming message rate (for example, due to a slow network or high CPU usage), causing overflow, or
- because
newMessageLimitis configured, which intentionally limits how many realtime messages are delivered every 500 ms. Any messages exceeding the configured limit within that window are discarded.
info.droppedCountcontains the number of messages that were not delivered.- Use this when: Notifying users that some realtime messages were missed, monitoring the effects of
newMessageLimit, or logging dropped messages for debugging and observability.
-
options: This object specifies the subscription options. You can set following properties:oldMessageLimit(number) — how many old messages to receive. Pass0to receive none. If omitted, all old messages are delivered. Default: all.- When to use: Cap the history for large sessions where loading every persisted message would be wasteful (e.g. only the last 50 messages need to appear when a participant joins).
realtimeOverflow("queue" | "drop") — behavior when your internet is slow or your device can't keep up."queue"(default) queues remaining messages so you receive them once you catch up;"drop"drops them instead.- When to use: Use
"queue"for chat where every message matters. Use"drop"for high-frequency, low-value streams (live reactions, cursor positions) where stale data is worse than missing data.
- When to use: Use
maxQueue(number) — maximum number of message batches to queue during overflow. Default:70. Max:200. Only valid withrealtimeOverflow: "queue".- When to use: Increase this value when you want to retain more messages and catch up after recovering from a slow network or CPU spike. Lower it if memory pressure matters more than history.
newMessageLimit(number) — maximum number of realtime messages to receive per 500 ms.- When to use: Set this when you want to render only a particular number of messages per second — for example, throttle a busy chat topic so the UI doesn't jank, or rate-limit a reactions topic.
If you call subscribe() again on the same topic with a different listeners object, the values of realtimeOverflow, maxQueue, and newMessageLimit are overridden by the latest subscribe() call. Other options (such as oldMessageLimit) are not affected.
Every message delivered to the listeners contains the following fields:
id— unique identifier for the message.message— the actual message content that was sent.senderId—participantIdof the participant who sent the message.senderName—displayNameof the participant who sent the message.timestamp— the timestamp indicating when the message was published.topic— the topic the message was published to.payload— any additional data sent along with the message (optional).
let meeting;
// Initialize Meeting
meeting = VideoSDK.initMeeting({
// ...
});
const listeners = {
onMessageReceived: (data) => {
let { message, senderId, senderName, timestamp } = data;
console.log(`New message received: ${message}`);
},
onBatchReceived: (messages) => {
// Handle a batch of realtime messages together
console.log(`Batch received with ${messages.length} messages`);
},
onOldMessagesReceived: (messages, { isLast }) => {
// Getting Old messages for upcoming participant
console.log(messages, isLast);
},
onMessageDrop: (info) => {
// Called when incoming messages are dropped
console.log(`Dropped ${info.droppedCount} messages`);
},
};
const options = {
oldMessageLimit: 50,
realtimeOverflow: VideoSDK.Constants.RealtimeOverflow.QUEUE,
maxQueue: 70,
newMessageLimit: 20,
};
async function subscribe() {
// Subscribe 'CHAT' topic
try {
await meeting?.pubSub?.subscribe("CHAT", listeners, options);
} catch (error) {
console.log("Error while subscribing to CHAT:", error);
}
}
unsubscribe()
- This method is used to unsubscribe from a particular topic.
- It will accept two parameters as input:
topic: The topic to be unsubscribed.listeners: The same listeners object that was passed insubscribe().
// The listeners object used during subscribe
const chatListeners = {
onMessageReceived: (data) => {
/* ... */
},
onBatchReceived: (messages) => {
/* ... */
},
onOldMessagesReceived: (messages, { isLast }) => {
/* ... */
},
onMessageDrop: (info) => {
/* ... */
},
};
meeting.on("meeting-left", async () => {
try {
await meeting.pubSub.unsubscribe("CHAT", chatListeners);
} catch (error) {
console.log("Error while unsubscribing from CHAT:", error);
}
});
Errors
publish() throws:
ERROR_ACTION_PERFORMED_BEFORE_MEETING_JOINED— called before the meeting is joined.ERROR_MEETING_RECONNECTING— the meeting is reconnecting.ERROR_INVALID_PARAMETER—messageis not a string orpayloadis not an object.PUBSUB_PUBLISH_FAILED— the publish request times out or the server returns an error.
subscribe() throws:
ERROR_ACTION_PERFORMED_BEFORE_MEETING_JOINED— called before the meeting is joined.ERROR_MEETING_RECONNECTING— the meeting is reconnecting.ERROR_INVALID_PARAMETER— any listener is not a function,maxQueuewas provided whilerealtimeOverflowis"drop",newMessageLimitis not greater than0,oldMessageLimitis less than0, or you calledsubscribe()on the same topic with a listener reference that was already registered.PUBSUB_SUBSCRIBE_FAILED— the subscribe request times out or the server returns an error.
unsubscribe() throws:
ERROR_INVALID_PARAMETER— any listener is not a function.PUBSUB_UNSUBSCRIBE_FAILED— the unsubscribe request times out or the server returns an error.
Applications of PubSub
PubSub is a very powerful mechanism which can be used to do a lot of things which can make your meeting experience much more interactive. Some of the most common usecase that we have come across for the PubSub during a meeting are listed below:
Chat: You can utilise this to develop features, like Private Chat or Group Chat. You can follow our chat integration guide here.Raise Hand: You can allow attendees to raise their hands at any point during the meeting, informing everyone else that someone has a question or input.Layout Switching: You can change the meeting's layout for every participant at once during the meeting, such as from Grid layout to Spotlight or from Grid Layout to Sidebar, etc.Poll: You can make polls, let users respond to them, and display the results at the end of a poll.Question Answer Session: You can also design interactive features based on a question-and-answer format.
Downloading PubSub Messages
All the messages from PubSub published with persist : true can be downloaded as an .csv file. This file will be accessible in the VideoSDK dashboard and through the Sessions API.
API Reference
The API references for all the methods and events utilized in this guide are provided below.
Got a Question? Ask us on discord

