---
title: "Realtime overview"
description: "How Realtime delivers events over WebSockets, covering channels, members and connections, the three channel types, and where usage shows up."
canonical: "https://bird.com/docs/guides/realtime/overview"
---

# Realtime overview

Realtime pushes events to connected clients over WebSockets. Your server publishes an event to a named channel, and subscribed clients receive it without polling.

Use Realtime for changes that a client needs without making another request, such as order updates, chat messages, dashboard changes, or completed background jobs.

## Channels, members, and connections

Three words describe the model. They are not interchangeable.

A **channel** is a named room. It exists while at least one connection is subscribed and disappears when the last one leaves. Channel names allow up to 164 letters, digits, and these characters: `_ - = @ , . ;`.

A **connection** is one open WebSocket. It receives an ID (`26896.319537`) when it connects. Authorization signs this ID, and publishing can exclude it from delivery.

A **member** is an authenticated identity on a presence channel. One member can hold several connections, such as three browser tabs. Presence events fire when the member's first connection joins and last connection leaves. Intermediate tabs do not produce them.

## The three channel types

The channel-name prefix selects the channel type and its authorization behavior.

| Name             | Who can subscribe                   | Has members |
| ---------------- | ----------------------------------- | ----------- |
| `orders`         | anyone holding the app key          | no          |
| `private-orders` | only clients your backend signs for | no          |
| `presence-lobby` | only clients your backend signs for | yes         |

A **public** channel is readable by anyone with the app key, which ships in client code. Publish only data that every visitor may see. See [Public channels](/docs/guides/realtime/public-channels).

A **private** channel asks your backend to approve each subscription. The client posts the connection ID and channel name to your endpoint, which returns a signature computed with the app secret. See [Private channels](/docs/guides/realtime/private-channels). A `private-encrypted-…` channel also encrypts payloads with a key held by your servers. See [Encrypted channels](/docs/guides/realtime/encrypted-channels).

A **presence** channel adds an identity to private-channel authorization. Each subscriber receives the member list and changes through `member_id` and optional `member_info`. See [Presence channels](/docs/guides/realtime/presence-channels).

## Events the client receives

Application events are yours: you pick the name at publish time (`order-updated`, `message.created`) and bind a handler to it. Alongside those, the client re-emits lifecycle events under the `bird:` prefix, which you bind exactly like your own:

- `bird:subscription_succeeded` fires once per channel when the subscription is live. On a presence channel it carries the current member list, so you can render the room before anyone moves.
- `bird:member_added` and `bird:member_removed` fire on presence channels as members arrive and leave. `member_added` fires when a person's first connection subscribes; `member_removed` only when their last one goes. A second tab opening and closing produces neither.
- `bird:connection_count` reports how many connections are subscribed to a public or private channel, if the app has connection counting and connection count events enabled. Presence channels do not emit this event; read their connection count with a [server-side channel query](/docs/guides/realtime/querying-channel-state).
- `bird:subscription_error` fires when a subscription is refused, most often because authorization failed.

Names beginning `client-` are reserved for events clients send directly to each other, which is a separate app setting and only allowed on private and presence channels.

Your server can also receive events, as webhooks, when a channel becomes occupied or vacated and when members join or leave. Those arrive as `realtime.*` events through the same webhook endpoints as the rest of Bird.

## The clients

Three clients receive events through the same protocol. Use `@messagebird/realtime` for browsers and Node.js, [`BirdRealtime`](/docs/sdks/swift) for iOS, macOS, and Linux, or [`com.messagebird:bird-realtime`](/docs/sdks/kotlin) for Android and the server JVM. Each supports subscriptions, bindings, presence, `signin()`, and client events.

Keep the app secret on your server. Server SDKs use it to publish events, authorize channels, and disconnect members.

## Apps, keys, and regions

An app is an isolated environment with its own credentials and its own channel namespace. Two apps never see each other's channels, which is what makes an app the right boundary between your staging and production environments.

Each app uses an immutable region selected at creation. Use [List Realtime regions](/docs/api/reference/list-realtime-regions) to retrieve the accepted identifiers, and choose the region closest to your users.

Each app has three values with different uses:

- The **app ID** (`rap_…`) identifies the app in Bird API calls and appears in each `/v1/realtime/apps/…` path.
- The **key** is public. Browsers connect with it, and it is safe to ship in client code.
- The **secret** pairs with the key to authenticate server-side calls and to sign channel authorization. It is shown once, at creation. Anyone holding it can publish to your app and forge presence identities.

Manage apps and rotate keys on the [Realtime apps](https://bird.com/dashboard/w/realtime/apps) page. Create a second key, deploy it, and then revoke the old key.

## Visibility

The [Realtime metrics](https://bird.com/dashboard/w/realtime/metrics) page reports three values per app or across the workspace for your selected window:

- **Max connections** is the highest number of connections open at the same moment inside the window. This peak is the value the connection limit applies to.
- **Average connections** is the mean of the daily peaks. It does not average every sample. A workspace that spikes each afternoon and idles overnight shows an average well above its quiet hours.
- **Messages** counts event deliveries, one per channel: a publish naming 50 channels counts as 50. It also includes the events the protocol sends on your behalf, so presence joins and connection-count updates land in the same number, which is why it can run ahead of the publishes your code made.

Usage is aggregated in one-minute buckets, so recent traffic can take several minutes to appear. The usage API is currently available only to the dashboard. For programmatic visibility, record publishes in your systems or derive activity from `realtime.*` webhooks.

## Plans and limits

The free plan covers 100 concurrent connections and 200,000 messages per day, across all of a workspace's apps. Creating more apps does not raise the ceiling, because it applies to the workspace.

Paid plans start at $25 per month for 250 concurrent connections and 500,000 messages per day, and scale to 30,000 connections and 90 million messages per day. [Realtime pricing](/products/realtime/pricing) lists every step.

Per-request caps apply on every plan: one publish names at most 100 channels, a batch carries at most 10 events, and an event payload is capped at 10 KB serialized.

## Next steps

- [Send your first realtime event](/docs/get-started/send-your-first-realtime-event) walks the whole loop end to end.
- [Publishing events](/docs/guides/realtime/publishing-events) covers publishing from your server, batching, and excluding the originating client.
- [Authorizing channels](/docs/guides/realtime/authorizing-channels) is the contract your backend implements for private and presence channels.

## Related resources

- [Realtime](/realtime-api) (product)
- [Build your first integration](/learn/paths/integration) (course)

[Get an implementation brief](/learn/workspace?topic=realtime)
