Sync / Replicated state
What you still own
The packages leave deliberate gaps, each a deployment decision:
- Authentication. Verifying tokens or sessions and deriving the principal per connection, and closing a socket when a credential expires.
- Compaction and retention. When to
compact, when tovacuum, and how long to keep the identity rows that make old retries recognizable. A rotated database forgets them; reject work older than the retained window rather than applying it as new. - Effect identities. A stable key per document, operation, and semantic action, chosen before the action runs and handed to the provider.
- Migrations. Sync and Durable version and refuse their own storage and wire formats. Your Message and snapshot payloads are yours to evolve.
- Browser storage policy. IndexedDB can be evicted; what to tell the user and when to ask for persistent storage.
Using one without the other
Sync without Durable. Any server that implements the exchange above, with the same validation, serves a replica: check the cursor, commit pending in order, answer the tail, acknowledge, reject, checkpoint, name its epoch.
Durable without Sync. The journal takes your own operation and snapshot codecs, an empty snapshot, a reducer, and an operation identity; the Durable README starts there.
When not to use replicated state
- No offline editing and no multi-device agreement is needed: plain Foldkit.
- The server owns the fact and the client can refetch it:
foldkit-remote. - Every peer must accept writes and merge without a server order: a CRDT
design.
Sync.lww.registerchanges the merge rule for one field only. - You want a database for arbitrary queries: Durable is an operation journal.
- You expect application-domain history to be migrated for you.