CRDTs & Conflict Resolution
1 / 17
Two users edit offline. Both changes are valid. Network later reconnects. What should the system do?
Bad answer: choose one whole document and discard the other.
Build data types that allow local updates and later convergence.
Not magic. Not “eventual consistency” as a slogan. A concrete merge/apply design.
For state-based CRDTs:
These mean order, batching, and duplicate delivery do not change the result.
Problem: max integer loses concurrent increments.
Solution:
Metadata preserves intent.
Two G-Counters:
Never merge only the final integer.
Higher timestamp wins. Tie-break deterministically.
Useful for low-value overwrites. Dangerous for user-created content.
Question: what work are we willing to lose?
Wall clocks answer: what time did the machine say? Vector clocks answer: what did this event know?
Outcomes:
Keep all values that are not causally dominated.
This converts hidden data loss into visible conflict resolution.
Adds get unique tags. Removes remove observed tags only.
Concurrent add and remove can preserve the add.
Real structures compose CRDTs.
Example:
ShoppingCart = OR-Map<ProductID, PN-Counter>
Indexes are unstable.
“Insert at index 5” means different things after concurrent edits.
Use stable character IDs instead.
Insert operation:
insert value V with id A#7 after parent B#3
Delete operation:
delete target A#7
Render deterministically.
Deleted characters stay as invisible anchors.
They preserve positions for operations that arrive later.
Needed pieces:
Build a collaborative browser editor.
Provided:
Learner implements:
Open two tabs. Type concurrently. Sync. Both converge. Duplicate delivery does not duplicate characters. Delete-before-insert still works.