Publishing messages with PubNub

Publishing is how a client sends data into PubNub. This page explains what the publish call does, what its response tells you, what PubNub guarantees about delivery, and where those guarantees stop.

One constraint holds throughout: a publish addresses exactly one channel, and a successful publish confirms that PubNub accepted the message, not that any particular client received it. For the calls and payload shapes that put this model into practice, refer to Send different message types.

Publish model​

You publish to one channel at a time. There is no broadcast API that addresses several channels in one call. To deliver the same payload to several channels, publish separately to each one.

A channel group does not change this. A group is a subscribe-side convenience, so you publish to a member channel and the clients subscribed to the group receive it.

PubNub places no limit on how many publishers a channel or keyset has, and a client can issue many publishes on the same connection without waiting for a response to each one.

There is no hard publish rate limit for a keyset in good standing. As a best practice, keep publish rates at 10 to 15 messages per second per channel. Faster rates are possible, but a slow subscriber can fall behind the connection's message buffer.

A message is the basic unit of data flowing through PubNub, and its payload is any JSON-serializable value. That value can be an object, an array, a string, or an integer. String content in a message payload can include any single-byte or multi-byte UTF-8 character. PubNub SDKs serialize the value for you, so you don't serialize a JSON object before passing it to the SDK.

The standard message payload size limit is 32 KiB. This includes the channel name and any metadata. A publish that exceeds it is rejected with HTTP 400 and this response body:

["PUBLISHED",[0,"Message Too Large","13524237335750949"]]

Publish response and the timetoken​

A successful publish returns three values:

[1,"Sent","14375189629170609"]
PositionValueMeaning
01Success flag, where 1 is success and 0 is failure
1"Sent"Human-readable response message
2"14375189629170609"Publish timetoken

PubNub assigns every published message a server-side timetoken: a monotonically increasing 17-digit value precise to 100 nanoseconds (10⁻⁷ s), the number of 100-nanosecond intervals since the Unix epoch. Divide a timetoken by 10,000,000 to get a Unix epoch value in seconds.

A PubNub timetoken exceeds the largest integer a JavaScript Number represents exactly, so increment or compare timetokens with an arbitrary-precision integer type such as BigInt rather than with plain numeric arithmetic.

Publish-processing latency, the time PubNub takes to accept and acknowledge a publish request, is about 0.5 ms within the same region.

The timetoken identifies the published message on its channel, which makes it the starting point for three separate features:

  • Message Persistence. Retrieve this specific message later by passing its timetoken as a boundary in a history call.
  • Message actions. Attach a reaction, a receipt, or another annotation to a message by referencing its timetoken.
  • Gap recovery. Track the last timetoken your app processed and replay from it after a disconnect.

For how timetokens are used across the rest of the platform, refer to Core concepts.

Delivery semantics​

At-most-once live delivery​

Live delivery to subscribers is at-most-once by default. On a stable connection, a subscriber receives each message at most once. After a reconnect, a replayed message can arrive again with the same timetoken. A subscriber can also miss messages if its buffer overflows or if it's disconnected when someone publishes a message.

PubNub does not deduplicate publishes on the server. Publishing the same payload twice always creates two distinct messages with two different timetokens.

If Message Persistence is enabled on your keyset, both of those publishes are stored as separate history entries.

For the transport that produces this behavior and the buffer that bounds the loss, refer to Data transport and delivery.

At-least-once delivery​

You can layer at-least-once delivery on top of the at-most-once live path by combining timetoken tracking with Message Persistence. Track the timetoken of the last message your app successfully processed, and after any disconnect or suspected gap replay history from that timetoken rather than assuming live delivery caught everything.

Replay is paginated, so page through the results with the timetokens each response returns until you have caught up. A single history call returns up to 100 messages for one channel, or up to 25 messages per channel across as many as 500 channels.

Exactly-once processing​

Exactly-once processing is a layer you add. Attach your own idempotency key to each payload and deduplicate on the receiving side. Do this in each subscriber, or centrally in a Function so every subscriber benefits without extra client code. PubNub does not deduplicate across publishes with different timetokens.

Some SDKs offer a narrower, subscribe-side deduplication that suppresses messages sharing the same timetoken, publisher, and payload. It is automatic in the Swift SDK and configurable through dedupOnSubscribe in the C#, Java, Kotlin, and Unity SDKs. It covers redelivery of one message rather than two distinct publishes, so it is not a substitute for an idempotency key. Check the configuration reference for your SDK in Available SDKs.

Publish retry​

By default, PubNub SDKs retry only subscribe operations, using exponential backoff for up to 6 attempts with delays growing from 2 to 150 seconds. Retrying a failed publish is therefore your application's decision. It can be a different decision per message type: retry immediately, retry with backoff, surface the failure to the user, or drop it.

Because nothing deduplicates on the server, a retry after an ambiguous failure can produce a duplicate. Treat each retry as a new publish and design consumers to tolerate the occasional duplicate.

At-least-once delivery with qos​

The REST publish API supports a qos (Quality of Service) parameter for cases that need delivery confirmation. Setting qos=1 makes the publish call wait until the message has been placed into each connected subscriber's receive buffer, which gives at-least-once semantics for the subscribers connected at that moment. If delivery fails, the call returns an error and can be safely retried, and each retry produces a new, distinct message.

qos is available only through the REST API. No PubNub SDK exposes it.

Message ordering​

Ordering is a property of the message rather than of the delivery path.

PubNub assigns every message a server-side timetoken when it accepts the publish. The timetoken records when PubNub accepted the message, which can differ from when the client sent it. History fetched through Message Persistence returns a channel's messages in timetoken order.

A subscriber receives live messages in the order they reach it, and each message carries its timetoken. Arrival order can differ from timetoken order and from one subscriber to another. Sorting a channel's messages by timetoken gives every client the same order. Timetoken order applies within a channel, so each channel's messages sort on their own.

That's what lets channels scale out without coordination between them.

Messages and signals​

PubNub carries two publish types. A message is the general-purpose unit for a full payload. A signal is a deliberately smaller unit for one frequently changing value. Signal payloads are limited to 64 bytes. That size difference is what usually decides between them, and the rest of the differences follow from it.

MessagesSignals
PersistenceOptionally stored by Message PersistenceNever stored
Mobile pushCan trigger mobile push notificationsCannot
Metadata (meta)SupportedNot supported
CostStandard message creditLower cost per operation
Typical useDurable, full-payload deliveryHigh-frequency, transient data

Use a signal for high-frequency, transient events such as a typing indicator, a live GPS update, or an IoT sensor reading. Use a message for everything else.

Send signals and messages on separate channels. Mixing them on the same channel interferes with how the SDK recovers missed events after a disconnect.

Publish metadata​

The meta parameter attaches data to a message that stays separate from the message payload. It serves two purposes:

  • Server-side filtering. PubNub evaluates a subscribe filter against meta.* as well as the payload. So PubNub can route or discard a message on values such as user role, priority, or region before it reaches a subscriber. The subscriber spends no bandwidth or battery on traffic it would have discarded.
  • Encryption compatibility. When message encryption is enabled, meta stays unencrypted and readable by PubNub services such as Functions and subscribe filtering, while the payload stays encrypted. Never put a secret in meta.

Metadata values must be JSON-serializable.

Next steps​

Was this page useful?

Last updated on