Presence Events

PubNub sends Presence events when users come online or go offline in your app.

You can receive these events in the client or use webhooks to keep a user's online and offline status up to date. Use presence events to track active and 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
Sent when a user subscribes to a channel.
leave
Sent when a user unsubscribes from a channel.
timeout
Sent when a subscriber is inactive on a channel for a set period. Default is 300 seconds for most SDKs. Configure the interval with presenceTimeout.

Optionally send heartbeats using heartbeatInterval to keep connections active and avoid timeouts.
state-change
Sent when a user's state changes.
interval
Sent in interval mode with occupancy and optional deltas.
Timeout detection

Presence timeout detection is not region-dependent. PubNub SDKs don't actively monitor connectivity. A disconnection is detected when subscribe requests time out (typically 300 seconds) or when the next request fails. Local network conditions drive timing differences, not PubNub's system.

Implicit vs. explicit Presence events

When you work with Presence, your app can signal that users are online in two ways. Think of a coffee shop: you can wave every few minutes (explicit) or people will see you when you move around (implicit).

First, understand how Presence tracking works. PubNub uses a timer for each user to decide when to mark them offline. The key is what resets this timer and how you configure the timeout.

PubNub tracks user activity automatically. Each subscribe call tells PubNub the user is active. This is implicit Presence and it runs by default. You can disable implicit heartbeats in the Presence Management page in the Admin Portal by clearing the Subscribe Heartbeats checkbox.

PubNub runs a timer per user. Each implicit heartbeat from the Subscribe API resets the timer. If a user is silent for the full duration, PubNub marks the user offline and sends a timeout event. The presenceTimeout setting controls this duration. It applies to both implicit heartbeats (Subscribe API) and explicit heartbeats (Presence Heartbeat API).

Why configure anything if PubNub tracks activity automatically? You may need faster disconnect detection than the default server ping interval (~280 seconds). Two settings determine when users are marked offline.

Configuration settings

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

  • presenceTimeout (also presenceHeartbeatValue or durationUntilTimeout in some SDKs) is the server-side timer. It sets how long PubNub waits without a subscribe call before marking a user offline. Default is about 300 seconds. Any explicit (heartbeat API) or implicit (subscribe API) heartbeat resets this timer.

  • heartbeatInterval (sometimes presenceHeartbeatInterval) is the client-side ping frequency. It controls dedicated "I'm still here" signals via the heartbeat API. 0 (default) sends no explicit pings and relies on implicit heartbeats. Any positive value (min 3 seconds) sends explicit heartbeats 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

Relying only on implicit Presence can delay disconnect detection. By default, the server expects the client to respond to a published message or an empty server ping every ~280 seconds. These server pings reset the long‑poll and act as implicit heartbeats. You may wait up to the full presenceTimeout (~300 seconds) before detecting a disconnect.

Explicit heartbeats help here. Set heartbeatInterval shorter than the server ping (for example, 120 seconds). The SDK then sends "I'm still here" signals more often. These explicit heartbeats reset the same Presence timeout and detect disconnects faster.

// 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

Every heartbeat is an API call. API calls incur cost. 1,000 users with a 60‑second heartbeat create 1,440,000 calls per day. If the default server ping (~280 seconds) is enough for your use case, explicit heartbeats may be unnecessary.

If you need rapid disconnect detection (for example, trading or emergency apps), use shorter heartbeat intervals for faster updates.

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 by SDK) and subscribe to a channel, the SDK automatically subscribes you to 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

To subscribe only to the Presence channel and not the main channel (to avoid increasing its occupancy, for example), subscribe to the main channel's -pnpres channel.

After you create the subscription with the receivePresenceEvents option enabled and add Presence listeners, call subscribe() to 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 switches to interval mode. In this mode, the join, leave, and timeout events are replaced by an interval event sent every few seconds with the total occupancy on the channel. You configure the Interval setting on 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