Channels and channel naming in PubNub

A channel is the name a publisher sends to and a subscriber asks for, and it is the only routing mechanism in PubNub's pub/sub model. Because a channel is a name rather than a declared resource, choosing names is the one piece of channel design you own. This page explains:

  • why the name is the entire contract between a publisher and a subscriber
  • what a valid channel name may contain
  • what the period in a dot-delimited name unlocks, and what depth costs
  • how a naming convention decides what you can address later
  • which problems a channel name does not solve

One rule holds throughout: PubNub matches channel names literally, so two sides communicate only when their strings are identical, and nothing warns you when a name has no counterpart on the other side.

The name is the entire address​

Channels are created implicitly the first time they are used and do not require provisioning. So there is no registry to declare a channel in, no schema to attach to it, and no owner recorded for it. The first publish or subscribe that uses a name is also what brings it into existence, and an application can therefore invent names at runtime as its conversations, matches, or device fleets appear.

Three consequences follow, and each one shapes how you generate names in code.

  • A typo is a valid channel. Publishing to chat.room.42 when subscribers are on chat.rooms.42 succeeds and returns a timetoken, because the misspelled name is a channel with no subscribers. Nothing errors. Deriving names from one function rather than composing string literals at each call site is what keeps the two sides in agreement.
  • Case counts as part of the name. PubNub channel names are case-sensitive. Chat.Room.42 and chat.room.42 are two unrelated channels, so a scheme that lowercases identifiers consistently avoids a class of near-miss bug that no error message will point at.
  • The keyset is the namespace. Channel names are scoped to a single keyset, so the same name on two keysets addresses two unrelated channels, even within the same account. That is what lets a test keyset carry the identical naming scheme as production without either one seeing the other's traffic.

What a valid name may contain​

A PubNub channel name is built from letters, digits, and the characters _ - = @ . ! $ # % & ^ ;. It cannot contain a comma (,), colon (:), asterisk (*), forward slash (/), backslash (\), whitespace, Unicode Null, or a non-printable ASCII character. Characters outside printable ASCII, such as emoji, are accepted but not recommended.

Channel names cannot exceed 92 UTF-8 characters. That ceiling applies to the whole name, not to any one segment, so every prefix and separator you add spends part of the same budget.

Two points about that grammar are easy to trip over.

  • An asterisk is not a channel name character, but it is meaningful in a subscribe pattern. alerts.* is a wildcard pattern, and a pattern is a way of naming a family of channels rather than a channel you can publish to. The following JavaScript is illustrative rather than a working application, and it shows the difference:

    1// A channel name: the literal string that both sides have to match
    2pubnub.publish({ channel: 'alerts.fire.building12', message: { level: 3 } });
    3
    4// A wildcard pattern: names a family of channels, and cannot be published to
    5pubnub.channel('alerts.*').subscription().subscribe();
  • Presence derives a second name from yours. When Presence is enabled, each subscribed channel has a companion channel named by appending -pnpres, which carries join, leave, and timeout events for it. Keep that suffix out of the names your application invents so a channel of your own never shares a name with a companion channel.

Validity is not the only reason to keep names short. Every currently subscribed channel name travels inside the subscribe request itself, so long names and large channel counts both grow that request toward its size ceiling. Refer to One connection carries every subscription and to API limits.

The period is the one structural character​

Every other valid character is ordinary text to PubNub. The period is different: it separates a name into levels, and several features read those levels.

FeatureWhat the levels let you do
Wildcard subscribeSubscribe to alerts.* and receive every channel matching the pattern, including channels that first carry traffic after the subscription started
FunctionsBind one Function to a channel pattern, such as chat.* or chat.team1.*, so a single deployment processes messages from every matching channel
Access ManagerGrant permissions with a RegEx pattern instead of enumerating channel names in the token

Wildcard subscribe requires the Stream Controller add-on with the Wildcard Subscribe option enabled on the keyset. Function pattern binding requires the same option. Enable it on your keyset in the Admin Portal.

Pattern depth is bounded, and the bound is what makes hierarchy a design decision rather than a free one. A pattern has to end in .*, so alerts.*.critical addresses nothing, and a pattern reaches only one of two positions in a name. A Function accepts chat.*, which matches every channel whose name begins chat., and chat.team1.*, which matches every channel whose name begins chat.team1.. The asterisk stands for a single segment, not for the rest of the name. For the wildcard subscribe ceiling, refer to API limits before designing a deep hierarchy.

Depth also reaches back into publishing. A channel name with more levels than a wildcard pattern can cover is subscribable, but publishing to it requires the Wildcard Subscribe option to be turned off on the keyset. A hierarchy that outgrows the pattern limit therefore costs you the feature that motivated the hierarchy. That is the practical argument for keeping names shallow and pushing detail into the last segment.

Where you place the first period is the decision that matters most, because a pattern can only divide a name where a period already sits. chat.team1.general gives you two boundaries to write patterns against, while chat-team1.general gives you one, because a hyphen is ordinary text to PubNub. When you want a boundary inside a name that patterns should not treat as a level, use a valid non-structural character such as - or _.

A convention decides what you can address later​

A reliable default is [channelType].[channelID], where the type identifies the purpose of the channel or the kind of messages it carries, and the ID identifies the specific room, user, device, event, region, or customer:

  • group.room123
  • inbox.user123
  • command.device123

The ID portion can itself be composed from several entities when one identifier is not enough to place the channel:

  • group.event123.room123
  • inbox.customer123.user123

There's a reason to prefer this over naming channels after a generated identifier, such as a User ID or a UUID. A random name can only be addressed one channel at a time. A prefixed name can be addressed as a set. That set is what a wildcard subscription, a Function binding, and a pattern-based Access Manager grant all operate on. A pattern grant matters in particular, because the number of channels a single grant can enumerate is capped, while a pattern is not. Refer to API limits and to Access Manager permission model.

A convention is also the cheapest thing to get right, because it is the hardest thing to change. PubNub has no built-in channel alias or redirect. Moving traffic to a better name therefore makes the old and new names two separate channels:

  • Stored history stays with the old name.
  • App Context metadata stays keyed to the old channel ID.
  • Any client still subscribed to the old name goes quiet, with no error.

Channels are shapes you impose, not types you choose​

PubNub defines no channel types. Every channel is the same object, and what distinguishes a private conversation from a stadium broadcast is only who publishes, who subscribes, and what their permissions allow. Four shapes cover most applications:

ShapeWho publishes and subscribesExample name
DirectTwo participants, each publishing and subscribingdirect.user1.user2
GroupMany participants, each publishing and subscribinggroup.family
BroadcastOne publisher, many subscribersbroadcast.announcements
AggregationMany publishers, one subscriber that collectsunicast.dataCollector

Nothing enforces these shapes. A broadcast channel stays one-to-many only because your application publishes from one place, or because Access Manager grants write on it to one identity and read to everyone else. Refer to Operations to permissions mapping.

The number of subscribers on a PubNub channel is unlimited. Splitting traffic across many narrow channels is therefore the usual first move, because a channel a client never subscribes to costs that client nothing. That makes channel design the cheapest filter you have. The limit on that approach is per client rather than per channel. One connection multiplexes many subscriptions, but the recommended channel count for a single client is bounded. That is where a channel group or a wildcard pattern replaces a long list of names. Refer to Three ways to name what you receive.

A channel group is worth distinguishing from a naming convention, because the two solve the same problem from opposite ends. A wildcard pattern keeps the decision in the name, so any channel matching the pattern is covered the moment it is used. A channel group keeps the decision on your server, so the client subscribes to one group name and your backend changes what that group holds without the client resubscribing. Group names cannot contain a period, so wildcards do not apply to them.

Each PubNub keyset supports up to 10 channel groups. Each group holds up to 1,000 channels by default. Paid plans can raise the cap to 2,000 channels per group.

What a channel name is not​

  • Not a security boundary on its own. With Access Manager disabled, any client holding your publish and subscribe keys can use any channel name on that keyset. An unguessable name is obscurity, not authorization. Access Manager makes channels the target of access control: a signed token carrying read or write on a channel is what actually restricts it. Channel names also travel inside the subscribe request, so keep personal data out of them.
  • Not a membership list. A channel is a routing address. Presence and App Context are two capabilities you layer on top of it: Presence tracks who is subscribed right now, and App Context memberships track who belongs to a channel regardless of whether they are connected.
  • Not a schema. A channel accepts any payload a publisher sends, so a subscriber cannot infer a payload shape from the channel it arrived on. Labeling traffic is what message types are for. Refer to Message types categorize traffic on a shared channel.
  • Not a configuration scope. The features a channel's events depend on, including Message Persistence, Presence, and Stream Controller, are enabled per keyset rather than per channel. Per-message choices, such as whether a publish is stored, are publish parameters instead. Refer to Publish.

Next steps​

  • Pub/Sub overview. The model a channel routes for, and what travels on one.
  • Subscribe. Subscriptions, multiplexing, channel groups, wildcards, and filtering.
  • Core concepts. Channels, messages, User IDs, timetokens, tokens, memberships, and channel groups.
  • API limits. Channel name length, wildcard depth, multiplexing guidance, and channel group ceilings.
  • Access Manager. Restricting who may publish to and subscribe to a channel.
  • App Context. Attaching persistent metadata to a channel.

Was this page useful?

Last updated on