Skip to content

Conflicts

“Conflict handling” in datadata is not one mechanism but several — and the useful way to organize them is by when a conflict gets resolved. The server keeps one authoritative history underneath all of it. Live editing settles conflicts the moment a write lands, with no human in the loop. Staged sessions defer resolution: the few conflicts that genuinely need a decision are surfaced for review rather than merged behind your back.

Outside a staged session, a conflict is settled the instant the write is processed. You never accumulate one to look at later.

  1. Server ordering. Every accepted change gets the document’s next sequence number. There is no distributed disagreement about history — the folder’s server is the authority.
  2. Last-write-wins by default. Two writers racing on the same field both land, in server sequence order; the later one overwrites the overlapping values. Nothing is dropped — the write with the higher sequence number simply wins.
  3. Guards, when you want detection. A write can demand that the document (or just the values it touches) hasn’t changed since the writer last saw it. A failed guard rejects the whole write cleanly — conflict detection without locking. The rejected write is dropped, not replayed; the caller refetches and retries.

Staged sessions — resolution deferred to review

Section titled “Staged sessions — resolution deferred to review”

A staged session defers the decision, not the detection — and it reuses the same guard mechanism. Every staged patch embeds test guards asserting the values its author saw; folding the staged patches, guards included, onto the live head either merges cleanly (disjoint upstream changes need no attention) or blocks the stage. Conflicts are derived from head and the patches — no per-document snapshot is stored. Anything that actually collides is surfaced and held until you resolve it (amend, drop, or rebase onto head) before commit. Nothing that collides is auto-merged behind your back.

Inside Yjs fields, concurrent edits always converge; there is nothing to detect or resolve — live or staged. This is structural, not just policy: Yjs deltas travel in their own sync lane and never advance the JSON sequence number that guards and conflict gates compare against — so someone typing in a document can’t fail your guard or block your stage.

datadata does not do operational transformation, and does not use CRDTs for structured data. As the live rules above spell out, it favors explicit, reviewable conflict handling — server-ordered last-write-wins with opt-in guards — over silently merging structured edits. Why we landed here, and what it costs, is covered in Design decisions.