Skip to content

Cursors

The SDK stores progress for each topic in its local database. A wire cursor is a sequence ID. Zero means the start of retained history. Sequence IDs can have gaps. The order is defined within each topic; do not use IDs to infer an order between topics.

The SDK keeps two positions for group and identity topics:

  • Received position (F): The topic prefix stored as pending envelopes or already handled. Storing the envelopes and advancing this position happen in one database transaction.
  • Processed position (P): The topic prefix applied to local state or rejected with a recorded terminal reason. This position cannot exceed F.

Both positions only move forward. A stream can advance F before the SDK can process the envelopes. If an envelope cannot be processed safely, it stays pending and blocks later envelopes on that topic. Other topics can still advance. A rejected envelope advances P only when the SDK has the state and preceding history needed to establish a terminal rejection.

Welcome topics track received progress and unresolved Welcomes. They do not use the group processed position. A later Welcome can complete while an earlier one remains unresolved.

A query names topics and an exclusive cursor for each topic. It returns retained envelopes after those cursors. Advance each topic only through the envelopes returned for that topic. has_more is true only when more matching rows exist in that query’s database snapshot. A page at the row limit can still have has_more = false.

Streams and queries use the same durable receipt and processing path. A stream reconnects from the received position. Overlap is safe: admission and processing prevent duplicate effects. A crash can leave received envelopes pending; the SDK resumes that work from the local database.

An explicit sync captures fixed topic targets. It completes after it processes those targets and the required discovery work. Later traffic does not extend that sync. A target from a read replica can lag the primary. A newest-envelope result or publish receipt supplies a target; it does not prove that the SDK has received all earlier envelopes.

CallScope
conversation.sync()That conversation’s group-message topic
conversations.sync()The installation’s Welcome topic and group discovery
conversations.syncAll()Welcomes and the selected conversation topics

conversations.sync() discovers conversations. Use conversation sync or syncAll() to fetch their message history.

Message history reads use the local database. They do not fetch new backend messages. The available history depends on the installation’s membership, backend retention, and the data it has already received and processed.

A message delivery cursor is separate from the wire cursor. It contains a local database identity and delivery number. It resumes local message delivery after that item. Default stream delivery advances when the app acknowledges an item by returning normally from its callback or requesting the next iterator item. A crash before the acknowledgement is stored can repeat an item. Deduplicate app effects with the message ID when needed.