Core concepts
Conflict resolution
How Syndra merges concurrent edits without losing data.
On this page
When two clients edit the same document at the same time or one edits offline for an hour Syndra has to merge their changes. It does this deterministically: every replica ends up with exactly the same result, with no central coordinator.
Merge rules
| Operation | Rule |
|---|---|
| Set an object key | Last writer wins, using hybrid logical clocks. |
| Insert into an array | Both inserts are kept, ordered by position then client id. |
| Delete from an array | Deletes win over concurrent edits to the same item. |
Edit text (Text) |
Character-level merge both edits are preserved. |
Increment a Counter |
Increments are summed. |
Choosing the right type
Plain objects are fine for most data. Reach for a specialised type when “last writer wins” isn’t what you want:
import { Text, Counter } from "@syndra/client"
const doc = syndra.doc("posts/hello", {
initial: {
title: "Hello",
body: new Text(""),
likes: new Counter(0),
},
})Why not operational transforms?
OT requires a central server to order operations. CRDTs merge on any replica, which is what makes Syndra’s offline mode and peer-to-peer sync possible.
Can I write a custom merge function?
Yes, register a resolver for a path pattern. It receives both values and their metadata and must
be a pure function. See Configuration.
What happens to a delete that races an edit?
The delete wins. The edited item is removed on every replica, and the edit is recorded in history so it can be restored with undo.