Presence Events

PubNub triggers presence events as users come online or go offline from the application.

Clients can receive these events directly or use webhooks to keep a user's online/offline status up to date. Use these events to keep track of active/inactive users and the total occupancy of the channel.

Presence webhooks

PubNub can invoke a REST endpoint on your server when presence events occur. For more information, refer to Events & Actions.

Presence event types

There are five main types of presence events:

EventsDescription
join
Fires when a user subscribes to a channel.
leave
Fires when a user unsubscribes from a channel.
timeout
Fires when the subscriber doesn't make any activity on a channel in a given period of time. By default, this occurs after 300 seconds for most SDKs. This interval can be customized on the client using the presenceTimeout property (the name can differ depending on the SDK).

Also, you can configure the client to send heartbeat intervals (using the heartbeatInterval property) to ensure periodic pings to avoid timeouts by signaling active connections.
state-change
Fires anytime the user's state is changed.
interval
Fires in interval mode to provide an occupancy count and optionally include delta changes.
Timeout detection

Presence timeout detection is not region-dependent. PubNub SDKs don't actively monitor connectivity - disconnection is detected when subscribe requests timeout (typically 300 seconds) or when the next request fails. Regional timing differences are due to local network conditions, not PubNub's system.

Implicit vs. explicit Presence events

When working with PubNub Presence, it's helpful to understand that there are actually two different ways your application can signal that users are still online. Think of it like this: imagine you're in a coffee shop and want others to know you're still there. You could either wave at people every few minutes (explicit), or just let them notice you whenever you get up to order coffee (implicit).

But first, let's understand how PubNub fundamentally tracks Presence. At its core, PubNub operates on a simple timer system: each user has an invisible countdown timer that determines when they should be marked as "offline." The key insight is understanding what resets this timer and how you can configure the timeout period.

How PubNub tracks users

PubNub automatically tracks user activity as part of its core operation. Every time your client makes a subscribe call to PubNub servers, PubNub treats this as proof that the user is still active. This is called "implicit Presence" and it runs continuously in the background by default. However, implicit heartbeats can be disabled through the Presence Management GUI in the Admin Portal by unchecking the Subscribe Heartbeats checkbox for the appropriate rule.

This creates an interesting dynamic. PubNub runs an internal timer for each user, and every time it receives an implicit heartbeat (via Subscribe API) from that user, it resets the timer back to zero. Only when a user goes completely silent for the full timer duration does PubNub mark them as offline and trigger a timeout event. This timer duration is controlled by the presenceTimeout setting - the same setting that applies to both implicit heartbeats (via Subscribe API) and explicit heartbeats (via Presence Heartbeat API).

So why configure anything if PubNub tracks activity automatically with server pings? The main use case for configuration is when you need faster detection of disconnected users than the default server ping interval of ~280 seconds provides. This is where configuration comes in - you have two main settings that control when users get marked offline.

Configuration settings

Before we dive deeper, let's understand the two main configuration options and how they work together:

  • presenceTimeout (also called presenceHeartbeatValue or durationUntilTimeout in some SDKs) is the server-side timer - it determines how long PubNub's servers wait without receiving a subscribe call from a user before marking them offline. The default is typically around 300 seconds (5 minutes) but can vary by SDK. This timer gets reset every time PubNub receives either an explicit heartbeat (via presence heartbeat API) or an implicit heartbeat (via subscribe API) from that user.

  • heartbeatInterval (sometimes called presenceHeartbeatInterval) is the client-side ping frequency - it controls whether your app proactively sends dedicated "I'm still here" signals (via presence heartbeat API) to reset that server timer. When set to 0 (the default), no explicit pings are sent and you rely purely on implicit heartbeats (via subscribe API) to maintain presence. When set to any positive number (minimum 3 seconds), your SDK automatically sends explicit heartbeat pings at that interval.

Think of it this way: presenceTimeout is like a countdown clock on PubNub's servers, and heartbeatInterval is like setting an alarm on your phone to reset that clock before it runs out.

Now let's see how these work in practice. If you set your presenceTimeout to 300 seconds and a user's client sends an implicit heartbeat (via subscribe API) after 4 minutes of being idle, PubNub resets their timer back to zero. They won't time out until they've been completely inactive for another full timeout period. This is actually pretty smart - if someone is actively subscribed to your app, why mark them as offline?

When implicit Presence isn't enough

The challenge with relying only on implicit Presence comes when you need faster detection of disconnected users. By default, the server expects the client to respond to either an intentionally published message or an empty server "ping" issued every 280 seconds. These server pings reset the long poll subscription and act as implicit heartbeats, keeping their presence timer reset even for inactive users. However, this means you might wait up to your full presenceTimeout period (default ~300 seconds) before detecting that someone has actually disconnected.

This is where explicit heartbeats come in. When you configure heartbeatInterval to a value shorter than the server ping interval (e.g., 120 seconds instead of the default ~280 seconds), you're telling the PubNub SDK: "Send more frequent 'I'm still here' signals to detect disconnections faster." These explicit heartbeat signals (via Presence Heartbeat API) work just like the implicit ones (via Subscribe API) - they reset the Presence timeout timer, but allow for quicker detection when users actually go offline.

// Let users rely on natural activity to stay present
{
presenceTimeout: 300, // 5 minutes until timeout
heartbeatInterval: 0 // No explicit heartbeats
}

// Send regular "I'm alive" signals regardless of activity
{
presenceTimeout: 300, // 5 minutes until timeout
heartbeatInterval: 120 // Heartbeat every 2 minutes
}

Cost vs. accuracy trade-off

Here's where it gets practical. Every heartbeat is an API call, and API calls cost money. If you have 1,000 users and each sends a heartbeat every 60 seconds, that's 1,440,000 extra API calls per day. For most applications where the default server ping interval (~280 seconds) provides adequate disconnection detection, these explicit heartbeats might be unnecessary overhead.

But for applications requiring rapid disconnection detection (like trading platforms or emergency systems), explicit heartbeats with shorter intervals provide faster notification when users actually disconnect, rather than waiting for the full presenceTimeout period.

Real-world scenarios

Here's how to configure these settings for different types of applications:

Chat applications

Most chat users are naturally active, so you can usually rely on implicit Presence with server pings. Set heartbeatInterval: 0 and let the default server ping interval (~280 seconds) maintain user presence. If someone's connection drops for your full presenceTimeout period, they're probably actually disconnected.

Collaborative tools

For applications needing faster disconnection detection than the default ~280-second server ping interval, a shorter heartbeat interval like 120 seconds provides quicker notification when users disconnect. This might cost more but enables faster presence updates.

Mobile applications

Battery life matters. You might use a hybrid approach with a longer presenceTimeout (like 600 seconds) and longer heartbeatInterval (like 240 seconds). This gives inactive users more time before timing out while still sending occasional heartbeats.

Critical applications

Trading platforms, emergency communication systems, or real-time monitoring tools need immediate notification when someone disconnects. Use shorter intervals like heartbeatInterval: 30 with presenceTimeout: 120 for rapid detection.

Mixed strategies

Implicit Presence works alongside any explicit heartbeats you configure. This actually works in your favor. Even with heartbeatInterval: 0, if users are actively subscribing, they'll stay present. With heartbeats enabled, both implicit heartbeats (via subscribe API) and explicit heartbeats (via presence heartbeat API) will keep the Presence timer reset, giving you the most reliable tracking possible.

The key insight is that presenceTimeout works the same way regardless of your heartbeat settings - it's simply the maximum time PubNub waits to hear any sign of life (whether from implicit heartbeats via subscribe API or explicit heartbeats via presence heartbeat API) before marking someone as offline.

Understanding this balance between automatic implicit heartbeats (via subscribe API) and intentional explicit heartbeats (via presence heartbeat API) helps you design a Presence system that matches both your user behavior patterns and your budget constraints.

Add Presence listeners

Receiving presence events requires a Presence listener. Presence events will be received for all channels within a subscription to which you added the listener and enabled Presence events.

User ID / UUID

User ID is also referred to as UUID/uuid in some APIs and server responses but holds the value of the userId parameter you set during initialization.

Event DataDescription
action
The Presence event action type: join, leave, timeout, state-change, interval
channel
The channel on which the Presence action happened
occupancy
The total number of subscribers on the channel when the event occurred
uuid
The User ID of the client that published the message
timetoken
The timetoken when the Presence action took place (when PubNub published the event)
data
The state of the client that changed
subscription
The channel group or wildcard subscription pattern that the channel belongs to (if applicable)
subscription.addListener({
presence: function (p) {
const action = p.action; // Can be join, leave, timeout, state-change, or interval
const channelName = p.channel; // Channel to which the message belongs
const occupancy = p.occupancy; // Number of users subscribed to the channel
const state = p.state; // User state
const channelGroup = p.subscription; // Channel group or wildcard subscription match, if any
const publishTime = p.timestamp; // Publish timetoken
const timetoken = p.timetoken; // Current timetoken
const uuid = p.uuid; // UUIDs of users who are subscribed to the channel
}
}

Subscribe to Presence channel

When you enable the receivePresenceEvents option (name may vary across SDKs), and subscribe to a channel, the SDK automatically subscribes you the relevant presence channels.

Subscription with Presence

To receive Presence events, you subscribe with Presence and have Presence enabled on your keyset. Make sure you configure Presence to track Presence-related events for all or selected channels (through Presence Management rules).

Presence channels are sister channels where presence events are published. If you don't wish to subscribe to all presence channels in your list, you can subscribe to individual channels by appending -pnpres to the channel name. For example, the presence channel for ch1 is ch1-pnpres.

Subscribe to presence channel only

If you wish to only subscribe to the presence channel and not the main channel (to avoid increasing its occupancy, for example), subscribe to the main channel's presence -pnpres channel.

Once you've created the subscription with the receivePresenceEvents param enabled, and added presence listeners, call subscribe() to receive presence events. Your client will now start receiving presence events in real time as users join and leave channels.

// create a subscription from a channel entity
const channel = pubnub.channel('channel_1')
const subscription1 = channel.subscription({ receivePresenceEvents: true });

// subscribe and start receiving real-time updates
subscription1.subscribe();

If you want to subscribe to a bunch of channels but only want to listen for presence events on some of them, you can create two subscription sets: one with the receivePresenceEvents option enabled for the channels you want to receive Presence updates, and one without the option for channels you don't want to receive the updates. For more information about subscription sets, refer to Subscription types.

Presence event modes

The channel presence mode indicates when presence events are triggered for that channel. There are two modes: announce and interval. The mode is determined by the occupancy count (total actively subscribed clients on that channel) in relation to the Presence Announce Max setting on the Admin Portal.

This feature prevents high occupancy channels from becoming too noisy with presence events. If you require the announce mode to be in effect past 100 occupants, please contact PubNub Support.

Announce mode

If the channel occupancy is less than the Announce Max setting (defaults to 20), the channel is in announce mode. In this mode, join, leave, timeout and state-change events are sent to subscribed clients as and when they're triggered.

User ID / UUID

User ID is also referred to as UUID/uuid in some APIs and server responses but holds the value of the userId parameter you set during initialization.

{
"action": "join",
"channel": "chats.room1",
"subscribedChannel": "chats.room1-pnpres",
"timetoken": "15119466699655811",
"occupancy": 2,
"uuid": "user123",
"timestamp": 1511946669
}

Interval mode

When a channel's occupancy exceeds the Announce Max setting, the channel goes into interval mode. In this mode, the join, leave, timeout events are replaced by an interval event which is sent every few seconds with the total occupancy on the channel. The Interval setting is also configurable for the settings page.

Triggering state-change events

The state-change events are always triggered regardless of which presence mode is active on a channel.

Presence deltas

Additionally, you can enable the Presence Deltas setting from the Admin Portal. When this flag is enabled, interval events will also include a list of clients (User IDs) that joined, left or timed-out since the last interval event. The following is a simple representation of a Presence Delta event payload.

{
"action": "interval",
"channel": "chats.megachat",
"occupancy": 27,
"join": ["user123","user88"],
"leave": ["user20", "user11", "user14"],
"timeout": ["user42"],
"subscribedChannel": "chats.megachat-pnpres",
"timestamp": 1511947739,
"timetoken": "15119477396210903",
"hereNowRefresh": false
}
Here now refresh flag

Both the Presence Deltas on a channel in Interval mode and the Presence Interval Webhooks behave similarly when the payload size exceeds the maximum limit.

If the presence delta data increases the payload beyond the maximum publish size (32KB), the excess data is removed, and a hereNowRefresh flag is included in the payload. This flag indicates that you should use the Here Now API to retrieve the list of currently active User IDs.

Last updated on