Replay and Durable Delivery
Replay is a broker-side catch-up for load-balanced worker groups. It is not a general message-history feature. This page states exactly what it does so you can decide whether your design can rely on it.
The short version
- An ordinary client that reconnects gets its subscriptions restored. It does not receive the messages that were published while it was away.
- A subscription that was created fresh receives no history.
- A worker in a load-balanced group with a persistent session does get the tasks that were dispatched while the group was scaled to zero, and exactly one member of the group receives each one.
If your design needs "what did I miss", keep your own store and read it on connect. Blueprint SDKs cache what they have seen in memory and nothing more.
What replay does
Replay runs on the hosted platform only, where the durable delivery store is enabled and message recording is on. Self-hosted kraken ships with a no-op delivery store, so nothing is replayed there unless you configure a backend.
It fires when a connection that subscribed with loadBalance: true also identifies as a durable worker. A connection is a durable worker when its actor type is agent or orchestrator, which hold a persistent broker session, or when it has published room presence with persistent: true.
On that signal the broker reads the group's cursor, queries the recorded messages for that room that are newer than the cursor, in pages of 100 up to 10 pages, and atomically claims each one so that exactly one member of the group receives it. The first time a group is seen its cursor is set to "now" and nothing is replayed; later reconnects replay only what was dispatched after that point.
Replayed frames arrive between a replayStart frame carrying count and a replayEnd frame carrying replayed, and each message has isReplay: true in its metadata. Live messages that arrive during a replay are buffered and flushed afterwards, deduplicated by message id, so a worker sees each message once and in order.
What replay does not do
- It does not run for a plain subscription, whatever the actor type. Without
loadBalance: truethere is no group, no cursor, and no replay. - It does not run on an ordinary reconnect. Reconnection restores your subscriptions and nothing else.
- It does not honour per-topic
replayEnabledormaxReplayMessagessettings. The control plane stores those with the app's topic configuration, but the broker does not read them. Treat them as documentation of intent, not behaviour. - It does not read the app's retention setting. Retention governs message logging for the dashboard and the message-logs API, not delivery.
Which SDKs use it
Of the blueprint SDKs, only @nolag/queue workers and @nolag/voice orchestrator pools subscribe with loadBalance: true. @nolag/agents inherits the connection-level option for the tasks and tools topics when you construct the core client with loadBalance: true, and forces it off for the rest. The other blueprint SDKs never trigger replay.
For the core SDK, pass loadBalance: true (and optionally loadBalanceGroup) to the client, or per subscription, and connect with an agent or orchestrator actor:
import { NoLag } from '@nolag/js-sdk'
const client = NoLag(WORKER_TOKEN, {
loadBalance: true,
loadBalanceGroup: 'image-workers',
})
client.on('replay:start', ({ count }) => console.log('catching up on', count))
client.on('replay:end', ({ replayed }) => console.log('replayed', replayed))
await client.connect()
const room = client.setApp(APP_SLUG).setRoom('image-processing')
room.subscribe('jobs')
room.on('jobs', (job, meta) => {
if (meta.isReplay) console.log('missed while offline:', job)
})Related
- Quality of Service describes what delivery guarantees the broker does provide.
- Presence covers persistent presence and the
persistent: trueflag. - Queue SDK is the blueprint built on this behaviour.