PubSub - React
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.

usePubSub
To utilize PubSub in a meeting, VideoSDK provides a hook called usePubSub. This hook enables you to subscribe to any topic and publish to any topic, facilitating the exchange of messages and instructions seamlessly during the meeting.
The hook automatically subscribes to the topic on mount and unsubscribes on unmount — you never call subscribe / unsubscribe yourself.
publish()
- This method is used for publishing a message for a specific topic.
- It can be accessed from the
usePubSubhook 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 respectiveparticipantIdhere. 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.
// importing usePubSub hook from react-sdk
import { usePubSub } from "@videosdk.live/react-sdk";
function MeetingView() {
// destructure publish method from usePubSub hook
const { publish } = usePubSub("CHAT");
const handlePublishMessage = () => {
// publish message
const message = "Hello Everyone!";
try {
await publish(message, { persist: true });
} catch (e) {
console.log("Error while sending message through pubsub", e);
}
};
return (
<>
<button onClick={handlePublishMessage}>Publish Message</button>
</>
);
}
usePubSub() callbacks and options
usePubSub(topic, listeners?, properties?)returns{ publish, messages, topic }. The second argument is a listeners object (onMessageReceived,onBatchReceived,onOldMessagesReceived,onMessageDrop). The third argument is a properties object (maxMessages,bufferMessages,oldMessageLimit,realtimeOverflow,maxQueue,newMessageLimit).- It will accept following parameters as input:
topic: The topic to subscribe to and publish on.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 — trigger a notification, play a sound, or update message-specific state.
- Don't use this when: The topic is high-throughput (busy chats, live reactions, cursor positions). Firing once per message causes excessive re-renders — use
onBatchReceivedinstead, or pair withbufferMessages: falseand throttle inside the callback.
-
onBatchReceived(messages)— Called with an array of realtime messages; the same set surfaced one-by-one throughonMessageReceived, grouped for bulk handling.- Use this when: A single state update per batch is cheaper than one per message (large chat lists, virtualized rendering).
-
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.
-
properties: This object specifies the hook properties. You can set following properties:maxMessages(number | null) — Hard cap on the number of messages retained in the returnedmessagesarray. Once the cap is reached, the oldest messages are dropped to make room for new ones. Passnullto retain every message. Default:null.- When to use: Cap history on high-frequency topics to prevent unbounded memory growth. For example, keep only the last 100 messages in a busy chat.
bufferMessages(boolean) — Controls whether incoming messages accumulate in the returnedmessagesarray. Whentrue(default), messages are stored inmessagesand delivered to the callbacks. Whenfalse, messages are delivered only via the callbacks and themessagesarray is never populated. Default:true.- When to use: Set to
falseon high-throughput topics (thousands of messages per second) where retaining a re-rendering array is undesirable — handle messages manually insideonMessageReceived/onBatchReceivedinstead.
- When to use: Set to
oldMessageLimit(number) — How many old messages to receive. Pass0to receive none. If omitted, all old messages are delivered. Default: all.- When to use: Cap 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"/Constants.RealtimeOverflow) — Behavior when the client 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 throttle a busy topic so the UI doesn't jank, or rate-limit a reactions topic.
If usePubSub() is called again on the same topic with different values (for example, another usePubSub instance mounts for the same topic with a different listeners object or different properties), the values of realtimeOverflow, maxQueue, and newMessageLimit are overridden by the latest usePubSub() call. Other properties (such as oldMessageLimit) are not affected.
Every message in the messages array and every message delivered to the callbacks 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).
// importing usePubSub hook and Constants from react-sdk
import { usePubSub, Constants } from "@videosdk.live/react-sdk";
function ChatView() {
const listeners = {
onMessageReceived: (message) => {
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 }) => {
console.log("Old Messages published with persist:true Received", messages, isLast);
},
onMessageDrop: (info) => {
// Called when incoming messages are dropped
console.log(`Dropped ${info.droppedCount} messages`);
},
};
const properties = {
maxMessages: 100,
bufferMessages: true,
oldMessageLimit: 50,
realtimeOverflow: Constants.RealtimeOverflow.QUEUE,
maxQueue: 70,
newMessageLimit: 20,
};
// destructure publish method and messages from usePubSub hook
const { publish, messages } = usePubSub("CHAT", listeners, properties);
const handlePublishMessage = () => {
// publish message
const message = "Hello Everyone!";
try {
await publish(message, { persist: true });
} catch (e) {
console.log("Error while sending message through pubsub", e);
}
};
return (
<>
<button onClick={handlePublishMessage}>Publish Message</button>
<p>Messages: </p>
{messages.map((message) => {
return (
<p>
{message.senderName} says {message.message}
</p>
);
})}
</>
);
}
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.
The hook throws (during subscribe / unsubscribe on mount / unmount):
ERROR_ACTION_PERFORMED_BEFORE_MEETING_JOINED— hook mounted 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 the underlyingsubscribe()ran on the same topic with a listener reference that was already registered.PUBSUB_SUBSCRIBE_FAILED/PUBSUB_UNSUBSCRIBE_FAILED— the subscribe or unsubscribe request times out or the server returns an error.
Applications of usePubSub
PubSub is a powerful mechanism that can be employed to enhance the interactive aspects of your meeting experience. Some common use cases for PubSub during a meeting include:
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

