Learning path
Data Synchronisation — Status
Grounded in Replicache/Zero, Figma, Linear, Shapiro et al. and Kleppmann's Cambridge notes. What you can do, what is unlocked, and what is still gated. Updated after each calibration. See MISSION.md and RESOURCES.md.
Knowledge graph
graph TD A["Life of a mutation
mutator · mutation · pending · authoritative · rebase"] B["Who decides the order
happens-before · Lamport clocks · server sequence · LWW"] C["Merge is not add
join · commutative / associative / idempotent
state-based vs. op-based · SEC"] A --> D["Server decides vs. CRDT
Figma's argument · the OT sketch"] B --> D C --> D A --> E["Rejection & dependent mutations
what happens to the rest of the log"] B --> F["Op-based CRDTs
causal delivery · OR-Set · the retry trap"] C --> F B --> G["Vector clocks & multi-value registers
detecting concurrency instead of hiding it"] D --> H["Local-first
the seven ideals · where each engine sits"] F --> I["Hybrid logical clocks
CRDTs for Mortals"] D --> J["Multiplayer hard parts
reparenting cycles · undo · interleaving"] F --> J classDef mastered fill:#dcfce7,stroke:#16a34a,color:#14532d; classDef partial fill:#fef9c3,stroke:#ca8a04,color:#713f12; classDef inner fill:#dbeafe,stroke:#2563eb,color:#1e3a8a,stroke-width:3px; classDef outer fill:#f5f3ff,stroke:#7c3aed,color:#4c1d95,stroke-dasharray:5 3; classDef locked fill:#fafaf9,stroke:#d6d3d1,color:#a8a29e; class A,B,C inner; class D,E,F,G,H,I,J locked; click A "lessons/01-life-of-a-mutation.html" "Lesson 01" click B "lessons/02-who-decides-the-order.html" "Lesson 02" click C "lessons/03-merge-is-not-add.html" "Lesson 03"
Calibration — 2026-09-11
PARTIAL — the mutation lifecycle and rejection
Arrived with the model already sketched (a command log, authoritative server state, UI as a projection) and the right instinct on rejection: "commands after a failing command might be dependent on that command's semantics." What is missing is the vocabulary (mutator / mutation / pending / rebase) and the fact that the shipping engines take the opposite default — each pending mutation is re-run independently against the new authoritative state, and the dependency problem is left to the mutator's own code. Lesson 01.
GAP — what "last" means in last-writer-wins
Answered "when each change was performed" — wall-clock time. Physical clocks on two laptops disagree by more than the gap between two edits, and neither replica can tell. The literature's answers are a Lamport timestamp with a node-id tiebreak, or — Figma's route — the server's arrival order, which is the trivial total order. Lesson 02.
GAP — merge vs. update
Merged two G-Counter states by adding them ({a:7, b:7}). The merge is the pointwise max ({a:4, b:5}). Adding is an update; a merge must be safe to apply twice, which addition is not. This is the single most useful misconception to have surfaced: the whole state-based CRDT idea is that merge is a join — commutative, associative, idempotent. Lesson 03 is built around it.
GAP — state-based vs. operation-based
"I don't know." The distinction is what decides what the network must guarantee: state-based tolerates loss and duplication (best-effort broadcast is enough); op-based needs reliable, sometimes causal, delivery. Lesson 03 introduces it; the op-based side gets its own lesson later.
GAP — why Figma says it is not a CRDT system
Answered "it doesn't handle conflicts; it just does last-writer-wins." But an LWW register is a CRDT — the simplest one in Shapiro's catalogue. Wallace's actual reason: "CRDTs are designed for decentralized systems where there is no single central authority to decide what the final state should be"; Figma has one, so it drops the machinery that exists to do without it. Gated behind 02 and 03 because the argument needs both.
Lessons
- 01 The Life of a Mutation ready
- 02 Who Decides the Order? ready
- 03 Merge Is Not Add ready
- 04Server Decides vs. CRDT — Figma's argument, and the OT sketch unlocks after 01 + 02 + 03
- 05Rejection and Dependent Mutations unlocks after 01
- 06Operation-based CRDTs and Causal Delivery unlocks after 02 + 03
- 07Local-first — the seven ideals unlocks after 04
Teaching preferences
- Glossary-first. Introduce the canonical term, then use it. Map Martin's working terms (dirty / committing / committed) onto the literature's (pending / in-flight / confirmed) explicitly.
- Vendor-neutral where possible. Replicache/Zero words are the default because they are the most precisely documented; show the TanStack DB / Electric / Figma equivalents alongside.
- Stack is secondary. TypeScript because the sync-engine literature is in it, not because it matters.
- Cite inline; flag synthesis. Rejection handling and the command-log-vs-CRDT trade-off have no neutral source — say so in the lesson.