---
source_url: https://www.pubnub.com/docs/general/setup/connection-management
title: Connection Management
updated_at: 2026-06-04T11:10:33.511Z
---

> Documentation Index
> For a curated overview of PubNub documentation, see: https://www.pubnub.com/docs/llms.txt
> For the full list of all documentation pages, see: https://www.pubnub.com/docs/llms-full.txt


# Connection Management

All PubNub SDKs manage the connection for you, so you don't have to handle device- or platform-specific details. To get the most from PubNub, understand when an SDK creates connections and how to recover from network errors.

## Get connected

When you initialize a PubNub object, no connection exists yet. The object lets you call PubNub APIs such as Publish and Subscribe. The first API call creates the connection. The network returns success (with data) or an error.

Successful requests return HTTP status `200`. Errors return codes such as `400`, `404`, `413`, `414`, or `500`. You don't need to read these codes directly because SDKs surface them as status events in the status handler of your listener. Handling status events is the key to graceful recovery.

## Handle network interruptions

PubNub's automatic reconnection handles brief interruptions such as tunnels or switching from Wi‑Fi to cellular. [Autoreconnect](#reconnection-policy) delivers messages published during a dropped connection.

The default message queue size is 100 and each message persists for up to 20 minutes. If you publish more than 100 messages, older messages overflow and are discarded. Overflow discards the oldest messages (FIFO) during the drop.

To guarantee message availability, use [Message Persistence](https://www.pubnub.com/docs/general/storage) to retrieve historical messages.

## Connection types

There are two connection types: subscribe and non‑subscribe. A subscribe connection is for the Subscribe API. A non‑subscribe connection is for other APIs such as Publish, Here Now, and History.

### Subscribe connections

A subscribe request creates a long‑lived connection. The PubNub SDK sends an HTTP request to the PubNub Network with a list of channels to receive messages. When any client sends a message to one of those channels, the network responds with the message content and status `200`. The SDK continues to issue subscribe requests after each success.

If no messages arrive within 280 seconds (long‑poll expiration), the network returns `200` with no messages. The SDK then sends the next subscribe request.

This request/response cycle continues for the life of the client's PubNub instance.

##### Battle short attention span with long polling

I’m Edward. I lead a small engineering team. We built a real-time collaboration platform for schools so students, teachers, and parents can share messages and materials across devices.

School networks are tough: older hardware, mixed browsers, and proxies or firewalls that block traffic. We also needed to scale to tens of thousands of concurrent students. My team wanted to focus on product, not real-time plumbing.

We chose PubNub instead of running our own servers. PubNub scales globally and delivers messages quickly. It helps with [connection disruptions](https://www.pubnub.com/docs/general/setup/connection-management#connection-issues) and [mobile](https://www.pubnub.com/docs/general/setup/connection-management#mobile-app-connection-management). PubNub also supports [HTTP long polling](https://www.pubnub.com/blog/evaluating-long-polling-vs-websockets/) for legacy and low‑bandwidth environments. Long polling lets clients re‑establish connections automatically and receive data when it becomes available or when the [timeout](https://www.pubnub.com/docs/general/setup/connection-management#timeout-configuration) is reached.

PubNub let us support legacy systems without giving up scale.

### Non-Subscribe connections

A non‑subscribe connection is short‑lived. The SDK sends an HTTP request and the PubNub Network responds, typically within milliseconds (depends on the request).

:::note Custom domain
To optimize integration or meet branding and compliance needs, you can use a custom domain for PubNub endpoints. See [Use a custom domain](https://www.pubnub.com/docs/general/setup/data-security#custom-domain).
:::

### Connection timeout

All APIs except Subscribe have a connection timeout of `15` seconds (may vary by SDK). If the PubNub Network doesn't respond within the configured time, the SDK aborts and reports a `timeout` status event (`PNTimeoutCategory`).

### Timeout troubleshooting

Troubleshooting a timeout can be hard because the source may be the app, device, network, DNS, ISP, or the PubNub Network.

PubNub provides logs to help find the root cause. If the request never reaches the PubNub Network, add logging on all points of your path. Tools like [Catchpoint](https://www.catchpoint.com/) (a network monitoring service) can also help.

### Timeout configuration

Adjust the 15‑second default if needed. For example, if you publish stock prices every 250 ms, a 15‑second wait isn't helpful. A single publish may not matter because it’s quickly outdated. In that case, use a shorter timeout.

:::tip Connection timeout
See each [SDK's configuration docs](https://www.pubnub.com/docs/sdks) for the `connectionTimeout` option.
:::

### Subscribe

The first time you call Subscribe, the SDK opens a TCP socket and sends the request. If it succeeds, the SDK emits `PNConnectedCategory` (name may vary by SDK). See the connection status listener (for example, [Kotlin API](https://www.pubnub.com/docs/sdks/kotlin/api-reference/publish-and-subscribe#add-connection-status-listener)).

The status event includes all channels successfully subscribed in that request.

:::note SDKs
The event payload may vary across SDKs.
:::

```json
{
    "category": "PNConnectedCategory",
    "operation": "PNSubscribeOperation",
    "affectedChannels": ["ch1", "ch2"],
    "subscribedChannels": ["ch1", "ch2"],
    "affectedChannelGroups": [],
    "lastTimetoken": 0,
    "currentTimetoken": "15856996387695942"
}
```

If you were to make another subscribe request to new channels, the status event would only include those new channels, however your client is still subscribed to the previous channels.

```json
{
    "category": "PNConnectedCategory",
    "operation": "PNSubscribeOperation",
    "affectedChannels": ["ch3", "ch4"],
    "subscribedChannels": ["ch1", "ch2", "ch3", "ch4"],
    "affectedChannelGroups": [],
    "lastTimetoken": "15856996387695942",
    "currentTimetoken": "15856996387695942"
}
```

When you unsubscribe from one of those channels, the status event would not include a `category` for that but there is an `operation`.

```json
{
    "error": false,
    "operation": "PNUnsubscribeOperation",
    "statusCode": 200,
    "affectedChannels": ["ch1", "ch2"],
    "affectedChannelGroups": [],
    "currentTimetoken": "15856996387695942",
    "lastTimetoken": "15856996387695942"
}
```

You don't need to monitor this event unless you want confirmation that the unsubscribe succeeded.

## Connection issues

Network errors can occur. Make sure your app covers edge cases. Here are common issues.

### Connection drop

The SDK detects this and emits a status event to your Status handler:

`{"category":"PNNetworkDownCategory"}`

At this point, notify the user about connectivity issues. The app is disconnected and can't perform PubNub operations or other network calls.

:::tip Simulate a network disconnection
You can simulate a drop using your browser's dev tools by switching the network to Offline.
:::

### Reconnection

When the connection returns, the browser detects it and the SDK emits `PNNetworkUpCategory` to your Status handler:

`{"category":"PNNetworkUpCategory"}`

### Restore channels subscription

For the browser, the JavaScript SDK automatically resubscribes to the same channels when the network recovers, using the [restore](https://www.pubnub.com/docs/sdks/javascript/api-reference/configuration) configuration property. This is enabled by default as of JavaScript SDK version `11.0.0`.

When `restore` is `true` and [listenToBrowserNetworkEvents](https://www.pubnub.com/docs/sdks/javascript/api-reference/configuration#listen-to-browser-network-events) is enabled (the default), the SDK detects network loss and moves the client into the `disconnected` state. It skips `leave` events and preserves the current timetoken and active channel and channel group list, so the SDK can catch up on missed messages when connectivity is restored.

Set `restore: false` to disable this behavior. When disabled, the SDK resets the timetoken and channel and channel group list on network loss. You must re-subscribe manually when the `PNNetworkUpCategory` event fires and keep track of the channels and channel groups in local cache.

:::warning Automatic resubscribing only in JavaScript
Automatic resubscribe works only for the JavaScript SDK in a browser.
Other SDKs detect failures or timeouts and enter [reconnection policy](#reconnection-policy) mode. When a reconnect succeeds, the browser-based JavaScript SDK resubscribes to the same channels and channel groups and resumes from the last saved timetoken, so any messages published during the disconnection are delivered automatically.
:::

## SDK connection lifecycle

PubNub SDKs use standardized workflows for subscribe and presence loops and implement configurable auto‑retry policies for network issues. This ensures stable, predictable connections across languages.

##### Understanding the subscribe loop

When you call any subscribe method in the PubNub SDK, an internal mechanism called the subscribe loop is automatically initiated. This is a core part of PubNub's real-time functionality:

* The loop runs inside the SDK; you don't need to start or maintain it.
* It maintains a persistent connection to PubNub servers and [automatically reconnects](https://www.pubnub.com/docs/general/setup/connection-management#reconnection-policy) if the network drops.
* It receives and processes incoming messages, delivering them to your handlers or callbacks.
* It's optimized for minimal battery and network usage while remaining real‑time.

When you unsubscribe or call methods like `unsubscribeAll()`, the SDK automatically stops the subscribe loop for those channels.

Some lower-level SDKs expose [direct control of the subscribe loop](https://www.pubnub.com/docs/sdks/c-core/api-reference/misc#start-a-callback-subscribe-loop), but these are for advanced use cases only and aren't needed for typical implementations.

:::tip Automatic reconnection and permissions
SDKs don't automatically reconnect when Access Manager tokens expire. For token lifecycle handling, see [Access Manager](https://www.pubnub.com/docs/general/security/access-control#authorization-flow).
:::

### SDK statuses

During your application's lifecycle, there are a few statuses the SDK may emit that you can use to determine the state of the workflow. This section focuses on the statuses that are relevant to the subscribe workflow, but there are other statuses that are relevant to other workflows.

:::note Differences across SDKs
Not all SDKs emit all of the statuses, and some may present the additional error information differently. Consult your SDK's Status events documentation (for example, in [JavaScript](https://www.pubnub.com/docs/sdks/javascript/status-events)) for more information.
:::

| Status | Description |
| --- | --- |
| `Connected` | The workflow is running, and messages/events are being received. |
| `Disconnected` | The workflow isn't running; no messages arrive. Emitted only after a connection was established (Connected was emitted). If you call [disconnect()](https://www.pubnub.com/docs/sdks/javascript/api-reference/misc#disconnect), call [reconnect()](https://www.pubnub.com/docs/sdks/javascript/api-reference/misc#reconnect) to resume. Calling `subscribe()` alone won't reconnect. |
| `Connection error` | The workflow isn't running because [retries reached the maximum attempts](#reconnection-policy) while trying to connect. No messages arrived because the connection wasn't established. Includes an error object explaining why the connection failed. |
| `Disconnected unexpectedly` | The workflow isn't running because, after receiving messages, the client disconnected and [retries reached the maximum attempts](#reconnection-policy) when trying to reconnect. Includes an error object explaining why the client disconnected without user request. |
| `Subscription changed` | The SDK subscribed to new channels or channel groups. Triggered each time the channel or channel‑group mix changes after the initial connection. Includes the current list of subscribed channels and channel groups. |

### Reconnection policy

You can configure the automatic reconnection behavior of the SDK when you initialize the PubNub object. There are several configuration options (policies) available:

* [Linear](#linear): retry connection at set intervals for a set number of attempts
* [Exponential](#exponential): retry connection at exponentially longer intervals for a set number of attempts

:::note Reconnecting and usage
Retries don't count as transactions because none reach the PubNub network until one succeeds. At that point, retries stop.
:::

#### Default reconnection policy

By default, PubNub SDKs are configured to exponentially retry subscribe operations only. The subscribe connection is retried up to 6 times with the delay between failed attempts ranging from 2 to 150 seconds.

:::warning SDK reconnection policy parity
Certain SDKs do not retry subscribe operations by default. For more information on which operations are retried, refer to your SDK's configuration documentation, for example, [JavaScript](https://www.pubnub.com/docs/sdks/javascript/api-reference/configuration), [Kotlin](https://www.pubnub.com/docs/sdks/kotlin/api-reference/configuration), or [Python](https://www.pubnub.com/docs/sdks/python/api-reference/configuration).
:::

#### Reconnection policy details

The default maximum number of reconnect attempts is `10` for linear and `6` for exponential. The minimum retry interval for all policies is 2 seconds. A random jitter from 0.001 to 0.999 seconds is added to each attempt.

Some SDKs enforce upper bounds on these values, while others leave it to you to set appropriate limits. Refer to your SDK's configuration documentation for more information.

Currently, the following SDKs do not enforce upper bounds on these values:

* [JavaScript SDK](https://www.pubnub.com/docs/sdks/javascript/api-reference/configuration) as of version `11.0.0`
* [Python SDK](https://www.pubnub.com/docs/sdks/python/api-reference/configuration)

##### Linear

The linear reconnection policy has several configurable parameters. The table below uses Rust as an example, but note that the syntax and data types may differ across SDKs.

| Parameter | Description |
| --- | --- |
| `delay`Type: `u64` | The delay in seconds between failed retry attempts. |
| `max_retry`Type: `u8` | Number of times a request can be retried. |
| `excluded`Type: `Option<Vec<Endpoint>>` | Endpoints that won't be retried. Refer to [Exclude endpoints from auto retry](#exclude-endpoints-from-auto-retry) for more information. |

##### Exponential

The exponential backoff starts at `i = 0` and increases as `min_delay*2^i` until the max retry attempts. The interval never exceeds `max_delay`. Parameters:

| Parameter | Description |
| --- | --- |
| `min_delay`Type: `u64` | Minimum delay in seconds between failed retry attempts. |
| `max_delay`Type: `u64` | Maximum delay in seconds between failed retry attempts. |
| `max_retry`Type: `u8` | Number of times a request can be retried. |
| `excluded`Type: `Option<Vec<Endpoint>>` | Endpoints that won't be retried. Refer to [Exclude endpoints from auto retry](#exclude-endpoints-from-auto-retry) for more information. |

#### Exclude endpoints from auto retry

Our SDKs also let you exclude endpoints (features) from the retry policy. Excluding an endpoint turns off auto‑retry for that endpoint. See each [SDK's documentation](https://www.pubnub.com/docs/sdks) for details.

##### JavaScript

```javascript
// Example: Exclude the Message Send endpoint from auto retry using Linear policy
const pubnub = new PubNub({
  subscribeKey: "demo",
  publishKey: "demo",
  userId: "user123",
  retryConfiguration: PubNub.LinearRetryPolicy({
    delay: 3, // 3 seconds delay between retry attempts
    maximumRetry: 5, // Maximum 5 retry attempts
    excluded: [PubNub.Endpoint.MessageSend] // Exclude MessageSend endpoint
  })
});

// Example: Exclude multiple endpoints using Exponential policy
const pubnub = new PubNub({
  subscribeKey: "demo",
  publishKey: "demo",
  userId: "user123",
  retryConfiguration: PubNub.ExponentialRetryPolicy({
    minimumDelay: 2, // Start with 2 seconds delay
    maximumDelay: 60, // Maximum 60 seconds delay
    maximumRetry: 6, // Maximum 6 retry attempts
    excluded: [PubNub.Endpoint.MessageSend, PubNub.Endpoint.MessageStorage]
  })
});
```

##### Swift

```swift
// Example: Exclude an endpoint using Linear policy
let config = PubNubConfiguration(
  publishKey: "demo",
  subscribeKey: "demo",
  userId: "user123",
  automaticRetry: AutomaticRetry(
    policy: .linear(delay: 3.0),
    retryLimit: 5,
    excluded: [.messageSend]
  )
)
let pubnub = PubNub(configuration: config)

// Example: Exclude multiple endpoints using Exponential policy
let config = PubNubConfiguration(
  publishKey: "demo",
  subscribeKey: "demo",
  userId: "user123",
  automaticRetry: AutomaticRetry(
    policy: .exponential(minDelay: 2.0, maxDelay: 60.0),
    retryLimit: 6,
    excluded: [.messageSend, .messageStorage]
  )
)
let pubnub = PubNub(configuration: config)
```

##### Objective-C

```objectivec
// Example: Exclude an endpoint using Linear policy
PNConfiguration *config = [PNConfiguration configurationWithPublishKey:@"demo" 
                                                         subscribeKey:@"demo"
                                                              userId:@"user123"];

// Linear policy with excluded endpoints
config.requestRetry = [PNRequestRetryConfiguration configurationWithLinearDelay:3.0
                                                                  maximumRetry:5
                                                             excludedEndpoints:PNMessageSendEndpoint, 0];

// Example: Exclude multiple endpoints using Exponential policy
config.requestRetry = [PNRequestRetryConfiguration configurationWithExponentialDelay:2.0
                                                                       maximumDelay:60.0
                                                                       maximumRetry:6
                                                                  excludedEndpoints:PNMessageSendEndpoint, PNMessageStorageEndpoint, 0];

PubNub *pubnub = [PubNub clientWithConfiguration:config];
```

##### Java

```java
// Example: Exclude the Subscribe endpoint using Linear policy
PNConfiguration config = new PNConfiguration("user123");
config.setSubscribeKey("demo");
config.setPublishKey("demo");
config.setRetryConfiguration(
    RetryConfiguration.linear(
        3, // 3 seconds delay between retries
        5, // Maximum 5 retry attempts
        Collections.singletonList(RetryableEndpointGroup.SUBSCRIBE) // Exclude Subscribe endpoint
    )
);
PubNub pubnub = new PubNub(config);

// Example: Exclude multiple endpoints using Exponential policy
PNConfiguration config = new PNConfiguration("user123");
config.setSubscribeKey("demo");
config.setPublishKey("demo");
config.setRetryConfiguration(
    RetryConfiguration.exponential(
        2, // Start with 2 seconds delay
        60, // Maximum 60 seconds delay
        6, // Maximum 6 retry attempts
        Arrays.asList(RetryableEndpointGroup.PUBLISH, RetryableEndpointGroup.HISTORY) // Exclude multiple endpoints
    )
);
PubNub pubnub = new PubNub(config);
```

##### Rust

```rust
// Example: Exclude the Publish endpoint from auto retry using Linear policy
let keyset = Keyset {
    subscribe_key: "demo".to_owned(),
    publish_key: Some("demo".to_owned()),
    secret_key: None,
};

let client = PubNubClientBuilder::with_transport(Transport::with_reqwest())
    .with_keyset(keyset)
    .with_user_id("user123")
    .with_retry_configuration(RequestRetryConfiguration::Linear {
        delay: 3,  // 3 seconds delay between retries
        max_retry: 5,  // Maximum 5 retry attempts
        excluded_endpoints: Some(vec![Endpoint::Publish])  // Exclude Publish endpoint
    })
    .build()?;

// Example: Exclude multiple endpoints using Exponential policy
let client = PubNubClientBuilder::with_transport(Transport::with_reqwest())
    .with_keyset(keyset)
    .with_user_id("user123")
    .with_retry_configuration(RequestRetryConfiguration::Exponential {
        min_delay: 2,  // Start with 2 seconds delay
        max_delay: 60,  // Maximum 60 seconds delay
        max_retry: 6,  // Maximum 6 retry attempts
        excluded_endpoints: Some(vec![Endpoint::Publish, Endpoint::History])  // Exclude multiple endpoints
    })
    .build()?;
```

##### C-Core

```c
// Example: Exclude endpoints from auto retry using Linear policy
pubnub_retry_configuration_t* config =
    pubnub_retry_configuration_linear_alloc_with_excluded(
        PNRC_MESSAGE_SEND_ENDPOINT,  // Exclude Message Send endpoint
        PNRC_MESSAGE_STORAGE_ENDPOINT,  // Exclude Message Storage endpoint
        -1  // End of list marker
    );

// Apply configuration to PubNub context
pubnub_set_retry_configuration(pubnub, config);

// Example: Exclude endpoints with custom parameters using Exponential policy
pubnub_retry_configuration_t* config =
    pubnub_retry_configuration_exponential_alloc_with_options(
        2,  // Minimum delay between retries (2 seconds)
        60,  // Maximum delay (60 seconds)
        6,  // Maximum 6 retry attempts
        PNRC_MESSAGE_SEND_ENDPOINT,  // Exclude Message Send endpoint
        PNRC_HISTORY_ENDPOINT,  // Exclude History endpoint
        -1  // End of list marker
    );

// Apply configuration to PubNub context
pubnub_set_retry_configuration(pubnub, config);

// Don't forget to free resources when done
pubnub_retry_configuration_free(&config);
```

## Mobile App connection management

Mobile apps can run on screen or in the background. Use these tips to manage connections on mobile and ensure you receive the messages you care about.

### Mobile App connection use cases

Consider the following scenarios:

* [Scenario 1](#scenario-1): the app runs in background (offscreen), then returns to foreground. You want to catch up on messages sent while offscreen.
* [Scenario 2](#scenario-2): the app runs in background and loses connectivity. You want to notify the user about unread messages when the device goes online.
* [Scenario 3](#scenario-3): a gaming app goes offline briefly and reconnects. You want to show only the latest messages.

### Scenario 1

Goal: catch up on all messages sent while the app was in background.

First decide whether the app can unsubscribe from channels (and send a `leave` event) when going to background. If you keep subscriptions, catch‑up is still possible but more complex.

:::tip More Information
For more information about unsubscribing and presence events, refer to [Channel Subscriptions](https://www.pubnub.com/docs/general/channels/subscribe#unsubscribe-from-channels) and [Presence Events](https://www.pubnub.com/docs/general/presence/presence-events).
:::

#### With unsubscribing

If your app can unsubscribe as it transitions to the background, the overall flow of message catch-up might look as follows:

1. Your app keeps track of the last received message [timetoken](https://www.pubnub.com/docs/general/messages/publish#send-messages) using a [listener](https://www.pubnub.com/docs/general/messages/receive#add-an-event-handler).
2. On transition to background, your app [unsubscribes from all channels](https://www.pubnub.com/docs/general/channels/subscribe#unsubscribe-from-channels).
3. On transition to foreground, your app receives and caches new messages, but doesn't process them. At the same time, your app performs a [Message Persistence API](https://www.pubnub.com/docs/general/storage#retrieve-messages) request to fetch all messages sent since the last received message (increment the timetoken your app saved in the first step by 1 and use that as the `end` parameter). Note that you might need to paginate through the results when the number of missed messages may be high. To get the subsequent page, use the same `end` parameter and update `start` to be the earliest (smallest) timetoken received from the previous page. Continue to do that until you get 0 messages.
4. Send a subscribe call and use the latest (highest) timetoken received in the previous step to start subscribing to the channels/channel groups again.

#### Without unsubscribing

If your app can't unsubscribe as it goes to background, the flow may look like this:

1. Your app keeps track of the last received message [timetoken](https://www.pubnub.com/docs/general/messages/publish#send-messages) using a [listener](https://www.pubnub.com/docs/general/messages/receive#add-an-event-handler).
2. On transition to background, your app does nothing with regards to channels.
3. On transition to foreground, your app performs a [Message Persistence API](https://www.pubnub.com/docs/general/storage#retrieve-messages) request to fetch all messages sent since the last received message and store these messages / events without triggering code to handle them. Message Persistence should consider different channels.
4. Continue paginating though history until all messages from all channels have been stored.
5. When your app has stored all messages/events, handle them according to your business logic.

### Scenario 2

Goal: send a push notification about unread messages while the app was offline in background.

Register with a push provider such as FCM or APNs, enable Mobile Push in the [Admin Portal](https://admin.pubnub.com), and prepare the message payload.

When the [Mobile Push Notifications](https://www.pubnub.com/docs/general/push/send) feature is enabled, associate device push tokens with PubNub channels. When a message is published to a channel, associated devices receive it via FCM or APNs.

For more information on sending APNs and FCM notifications, refer to [iOS Mobile Push Notifications](https://www.pubnub.com/docs/general/push/ios) and [Android Mobile Push Notifications](https://www.pubnub.com/docs/general/push/android).

PubNub doesn't know if the app is in foreground or background. Delivery depends on the published message. If it has no push payload, no push notification is sent. The server always sends data in real time. If the data includes a push payload, it triggers a push notification.

### Scenario 3

Goal: display only the latest messages after a brief offline period (common in gaming).

1. Your app receives messages in real time using a [listener](https://www.pubnub.com/docs/general/messages/receive#add-an-event-handler).
2. On transition to background, your app [unsubscribes from all channels](https://www.pubnub.com/docs/general/channels/subscribe#unsubscribe-from-channels).
3. On transition to foreground, your app [subscribes](https://www.pubnub.com/docs/general/channels/subscribe#subscribe-to-channels) to all the channels it unsubscribed from on transition to background.

## Terms in this document

* **Access Manager** - A cryptographic, token-based permission administrator that allows you to regulate clients' access to PubNub resources, such as channels, channel groups, and user IDs.
* **PubNub** - PubNub is a real-time messaging platform that provides APIs and SDKs for building scalable applications. It handles the complex infrastructure of real-time communication, including: Message delivery and persistence, Presence detection, Access control, Push notifications, File sharing, Serverless processing with Functions and Events & Actions, Analytics and monitoring with BizOps Workspace, AI-powered insights with Illuminate.
