---
title: "Pusher"
description: "Use Pusher Channels for MainSDK real-time updates - app keys and cluster, main.yaml, private channels, local testing and swapping."
section: "integrations"
canonical: "https://mainsdk.dev/docs/integrations/pusher"
updated: "2026-10-28"
---

# Pusher

> Use Pusher Channels for MainSDK real-time updates - app keys and cluster, main.yaml, private channels, local testing and swapping.

Canonical: https://mainsdk.dev/docs/integrations/pusher · Updated: 2026-10-28

Pusher Channels is a hosted service for pushing messages to connected browsers and apps over WebSockets. In a MainSDK app it is the default driver behind [`realtime`](https://mainsdk.dev/docs/interfaces/realtime): your server calls `realtime.publish()`, and clients listening with `realtime.subscribe()` get the update without a refresh. Pick Pusher for live order status, dashboards and badges when you don't want to run your own WebSocket servers.

> **Note:** `realtime` has no spec yet. The keys and calls on this page are provisional, taken from the catalog and the product requirements, and may change when the spec lands.

## Interfaces it serves

### Realtime updates (`realtime`)

- Status: Building for 0.3 · ships as a beta API
- Driver: `pusher` (Pusher). later
- Docs: https://mainsdk.dev/docs/interfaces/realtime.md

```yaml
realtime:
  driver: pusher
```

Swap to another provider: `broadcast`, `local`, `ably`, `supabase-realtime`.

## Before you start

1. **Create a Channels app** in your Pusher account. Each app has an app ID, a key, a secret and a cluster (the region it runs in).
2. **Pick the cluster** closest to your users and, where it matters, in your MainSDK data region (US, EU or India).
3. **Create one app per environment**, so development traffic never reaches production clients.

The key is public by design; the secret is not. Store the secret in your secrets manager, never in code or the browser.

## Configure

```yaml title="main.yaml"
realtime:
  driver: pusher
```

How the Pusher driver takes its app ID, key, secret and cluster is not decided yet [TBD]; the secret will be a `secret:` reference such as `secret:PUSHER_SECRET` (suggested name).

## Use it

```ts title="app/orders/actions.ts"
"use server";
import { realtime } from "mainsdk";

export async function markShipped(orderId: string) {
  // update the order in db first
  await realtime.publish(`order:${orderId}`, { status: "shipped" });
}
```

On the client, `realtime.subscribe()` listens on the channel, for example `order:ord_1`; its exact signature arrives with the spec.

## Local development and testing

- `createTestApp()` from `@mainsdk/testing` runs `realtime` on its in-memory fake, so tests need no Pusher account.
- `chaos.on("realtime", { outage: true })` simulates a Pusher outage.
- Pusher's debug console shows messages on a development app as they are sent.

## What MainSDK adds on top

- Channel access checked per user and tenant, so a client only hears channels it may see. On Pusher, per-user access is what private channels are for; how MainSDK wires their authorisation step is [TBD].
- A new realtime update can go to a small share of users first and pause itself on spikes in errors, through the same staged rollout as notifications.

See [Real-time updates](https://mainsdk.dev/docs/interfaces/realtime).

## Limits and notes

- `realtime` is listed for phase 1, with no spec yet. How channel access rules are declared is not decided.
- Keep personal data out of messages; send IDs and statuses and let the client fetch details.
- Pusher limits message size and connection counts by plan; check yours against your traffic.

## Swap to or from it

```yaml title="main.yaml"
realtime:
  driver: ably   # was pusher
```

Broadcast holds no state in the provider, so it swaps with no migration. See [Swap a driver](https://mainsdk.dev/docs/guides/swap-a-driver).

## FAQ

**Can clients publish to a channel?** Not through the catalog calls: clients subscribe and your server broadcasts.

**Does Pusher give me presence?** Real-time collaboration and presence in MainSDK come in phase 5.

## Next

- [Real-time updates](https://mainsdk.dev/docs/interfaces/realtime)
- [Ably](https://mainsdk.dev/docs/integrations/ably) and [Supabase](https://mainsdk.dev/docs/integrations/supabase)
- [Swap a driver](https://mainsdk.dev/docs/guides/swap-a-driver)
