Guarantees and limits#

What the core guarantees, whichever adapter and store you use, and the limits it has. Each row links to the reason behind it.

Guarantees#

Guarantee

Why

A change set is applied whole or not at all, and the sync token moves only with it.

Why a change set is applied all at once

A sync that stops at any point loses nothing: the next one starts from the last sync token the store saved.

Why a change set is applied all at once

A change set fetched from an outdated token is refused, so two processes never apply the same changes twice.

Why a change set is applied all at once

Nothing is pushed until every page of a sync is ingested.

Why a sync reads before it writes

Two processes never claim the same push at once.

Why a sync reads before it writes

A pending edit stays until the server applies it. A rejected push, or one whose answer never arrived, doesn’t discard it.

Why the server’s answer to a write isn’t trusted

An object the server removed while you edited it is always a conflict, never resolved for you.

Why conflicts are reported, not resolved

A conflict that changed since you read it can’t be resolved, so a decision never applies to changes you haven’t seen.

Why conflicts are reported, not resolved

A server’s copy of your own write isn’t reported as a change, however the server rewrote it.

Why changes are compared by fingerprint

Everything a sync changes, every conflict you resolve and every scope you drop reaches the change feed in the same transaction, numbered in order, and a removal stays readable until you purge it. Your own edit reaches it when its push ends.

Why changes are read from a feed

A scope the server no longer has is never emptied for you. Dropping it returns the edits and conflicts it discards.

Why a removed scope is yours to drop

In the stores that ship, a read in another thread doesn’t wait for a sync’s write, at most for its commit, and sees the store as it was before the write began. A store over a storage of your own does the same where the storage sets reads_beside_writes.

Why storage is synchronous

Every store checks arguments and raises errors the same way, since the checks live in the base class.

StateStore

Limits#

Limit

Why

An edit that changes only values a server stamps on its own, such as when an object was last saved, isn’t pushed.

Why changes are compared by fingerprint

If two processes sync a scope at once, both can send the same edit. A guarded change or delete is then rejected, but a create whose id the server picks can exist twice where the adapter doesn’t treat logical keys as unique.

Why a sync reads before it writes

After a push is applied, the next sync fetches that object from the server once more.

Why the server’s answer to a write isn’t trusted

A full listing compares every object, and an adapter whose protocol has no version for each object fetches every one.

Why an invalid token is routine

A replica runs one sync of a scope at a time, and a second raises SessionError.

Why a sync reads before it writes

Store calls are synchronous. The asynchronous adapters run them in a worker thread.

Why storage is synchronous

A store restored from an older copy numbers new feed entries again from the copy’s point, so a cursor saved after the copy skips entries.

Back up and restore the store

calendaring-sync logs nothing. Your client library’s logging shows the requests an adapter sends.

Inspect and repair a scope

Each adapter’s own limits, and how each tested server behaves, are on Adapters and Server compatibility.

Last updated on 2026-10-28.