06
Deep Dive — OT vs CRDTs
This is the hard part of collaborative editing — and the concept that makes this problem unique. Two approaches exist, and understanding both is essential.
Why is concurrent editing hard?
The simplest example. Document says: AB
The Conflict Scenario
Alice
Inserts X at position 0
Expects:
XAB
Bob
Inserts Y at position 2
Expects:
ABY
If the server applies Alice's edit first (XAB), then Bob's "insert Y at position 2" gives XAYB instead of XABY. Bob's position is stale — Alice shifted everything right. The document is now corrupted.
Solution 1: OT — "Fix the Positions"
Think of a post office with a smart clerk. Every edit arrives at the server (the clerk). The clerk checks: "Has anything changed since this person sent this?" If yes, the clerk adjusts the position before applying.
Alice inserts X at 0 → applied first. Bob inserts Y at 2 → clerk sees Alice pushed everything right by 1, so transforms Bob's position from 2 to 3. Result: XABY. Both users converge.
sequenceDiagram
participant A as Alice (Browser)
participant S as Collab Server
participant B as Bob (Browser)
Note over A,B: Document: "AB" — Revision 1
A->>S: Insert(X, pos=0) based on rev 1
B->>S: Insert(Y, pos=2) based on rev 1
Note over S: Apply Alice → "XAB" (rev 2)
Note over S: Transform Bob: pos 2→3 (Alice shifted +1)
Note over S: Apply Bob → "XABY" (rev 3)
S-->>A: Bob's op (transformed): Insert(Y, pos=3)
S-->>B: Ack + Alice's op: Insert(X, pos=0)
Note over A,B: Both see "XABY" ✓
OT in one sentence
The server is a single referee that assigns a global order to operations and adjusts positions so that everyone's edits produce the same document — regardless of what order they arrived in.
Solution 2: CRDTs — "Don't Use Positions"
Completely different philosophy. Positions cause all the problems — so get rid of them. Give every character a permanent unique ID that never changes. Edits reference these stable IDs, not numeric positions.
The analogy: a train where every car has a unique name. You say "add a dining car between 'sleeper' and 'engine'." Someone else says "add a luggage car between 'engine' and 'caboose'." Both instructions work regardless of order because they reference names, not position numbers.
|
OT (Operational Transformation) |
CRDTs |
| Core idea |
Fix the positions after the fact |
Don't use positions at all |
| Needs central server? |
Yes — the referee |
No — works peer-to-peer |
| Memory overhead |
Light |
Heavier — metadata per character |
| Offline editing |
Hard — large batch transforms |
Natural — just sync on reconnect |
| Complexity |
Transform functions are bug-prone |
Data structure design is complex |
| Used by |
Google Docs |
Figma, Yjs, Automerge |
Our choice: OT. We already need a server for auth, storage, and permissions. OT's lower memory footprint fits better, and it's the expected answer in interviews. But the industry trend is moving toward CRDTs — worth mentioning as the modern alternative.