Open a Google Doc. Share it with ten colleagues. Everyone starts typing simultaneously.
No conflicts. No merge issues. No "your changes were overwritten." Every keystroke from every user appears in real-time, and somehow the document stays consistent for everyone.
This feels like magic. It's actually one of the most elegant algorithms in distributed systems: Operational Transformation (OT).
And understanding how it works will fundamentally change how you think about distributed state.
The Problem That Seems Impossible
Consider two users editing the same document simultaneously:
1Initial document: "ABCD"
2
3User 1: Insert "X" at position 1 → "AXBCD"
4User 2: Delete character at position 3 → "ABD"
If we naively apply both operations:
- Apply User 1's insert, then User 2's delete at position 3: "AXBD" ← deletes "C" ✓... wait
- Apply User 2's delete, then User 1's insert at position 1: "AXBD"
Okay, that worked by coincidence. Now try this:
1Initial document: "ABCD"
2
3User 1: Insert "X" at position 1 → "AXBCD"
4User 2: Insert "Y" at position 1 → "AYBCD"
Apply both naively:
- User 1 first, then User 2 at position 1: "AYXBCD"
- User 2 first, then User 1 at position 1: "AXYBCD"
Different results. The document has diverged. This is the fundamental problem of real-time collaboration.
Operational Transformation: The Core Idea
OT's insight is deceptively simple: when you receive a remote operation, transform it against all operations that have been applied locally since the remote operation was created.
The transformation function adjusts the operation's position to account for what's changed.
1transform(op1, op2) → (op1', op2')
2
3Where:
4 apply(apply(document, op1), op2') = apply(apply(document, op2), op1')
This is called the transformation property — no matter which order operations are applied, the result must be the same.
Concrete Example
1Document: "ABCD"
2User 1: Insert("X", position=2) → intended result: "ABXCD"
3User 2: Insert("Y", position=1) → intended result: "AYBCD"
User 1 receives User 2's operation. But User 1 has already applied their own insert at position 2. We need to transform User 2's operation:
1User 2's op: Insert("Y", position=1)
2User 1's op: Insert("X", position=2)
3
4Since User 2's insert position (1) < User 1's insert position (2):
5 User 2's op is unchanged: Insert("Y", position=1)
6
7User 1's document after both: "ABXCD" → Insert("Y", 1) → "AYBXCD"
User 2 receives User 1's operation and transforms it:
1User 1's op: Insert("X", position=2)
2User 2's op: Insert("Y", position=1)
3
4Since User 1's insert position (2) >= User 2's insert position (1):
5 Shift User 1's position by 1: Insert("X", position=3)
6
7User 2's document after both: "AYBCD" → Insert("X", 3) → "AYBXCD"
Both users arrive at "AYBXCD". Consistency achieved.
The Transformation Functions
For a basic text editor, you need transformations for every pair of operation types:
Insert vs Insert
1transform(Insert(char1, pos1), Insert(char2, pos2)):
2 if pos1 < pos2:
3 return (Insert(char1, pos1), Insert(char2, pos2 + 1))
4 else if pos1 > pos2:
5 return (Insert(char1, pos1 + 1), Insert(char2, pos2))
6 else:
7 // Tie-breaking by user ID
8 return based on user priority
Insert vs Delete
1transform(Insert(char, insPos), Delete(delPos)):
2 if insPos <= delPos:
3 return (Insert(char, insPos), Delete(delPos + 1))
4 else:
5 return (Insert(char, insPos - 1), Delete(delPos))
Delete vs Delete
1transform(Delete(pos1), Delete(pos2)):
2 if pos1 < pos2:
3 return (Delete(pos1), Delete(pos2 - 1))
4 else if pos1 > pos2:
5 return (Delete(pos1 - 1), Delete(pos2))
6 else:
7 // Both deleting the same character — one becomes a no-op
8 return (NoOp, NoOp)
These look simple. They are simple. The complexity explosion happens when you have more than two concurrent users and operations arrive in different orders.
Google's Implementation: Jupiter Protocol
Google Docs uses a centralized OT architecture internally called Jupiter (later evolved for Google Docs specifically):
1 ┌──────────┐
2 │ Server │ ← Single source of truth
3 └────┬─────┘
4 │
5 ┌─────────┼─────────┐
6 │ │ │
7┌───┴──┐ ┌───┴──┐ ┌───┴──┐
8│User 1│ │User 2│ │User 3│
9└──────┘ └──────┘ └──────┘
Key design decision: The server is the authoritative ordering point. When conflicts occur, the server decides the canonical order. Clients transform their local operations against the server's decisions.
This simplifies the problem enormously. Instead of every client needing to resolve conflicts with every other client (O(n²)), each client only resolves conflicts with the server (O(n)).
The Client-Server Flow
11. User types → Operation applied locally (optimistic)
22. Operation sent to server
33. Server applies operation (transforming if needed)
44. Server broadcasts transformed operation to all other clients
55. Other clients transform and apply
The user sees their changes instantly (step 1). Consistency with other users is achieved asynchronously (steps 2-5). This optimistic approach is why Google Docs feels so responsive.
Why OT Is So Hard to Get Right
If OT is so elegant, why did it take decades to build reliable collaborative editors?
The Puzzle of Convergence
With two users, you need one transformation function. With three concurrent operations, you need the transformations to be composable — transforming A against B, then the result against C, must yield the same result regardless of order.
This property (called TP2 in the academic literature) is notoriously difficult to prove correct. Google's implementation went through years of testing and formal verification.
Edge Cases Are Endless
Consider: User 1 selects text and bolds it. User 2 deletes half that text while User 1 is bolding. User 3 inserts text in the middle of the selection. What's the correct bold range now?
Formatting operations, cursor positions, selection ranges, undo/redo — each adds combinatorial complexity to the transformation functions.
CRDTs: The Alternative Approach
The research community developed an alternative: Conflict-free Replicated Data Types (CRDTs).
Instead of transforming operations, CRDTs design data structures where concurrent operations automatically commute — they produce the same result regardless of order.
For text editing, a CRDT assigns a unique, globally-ordered ID to each character:
1"HELLO" represented as:
2 H(id: site1.1)
3 E(id: site1.2)
4 L(id: site1.3)
5 L(id: site1.4)
6 O(id: site1.5)
Inserting between characters is always unambiguous because every position has a unique ID. There's no "position 3" that shifts — there's "between site1.2 and site1.3."
Advantages of CRDTs:
- No server needed — truly peer-to-peer
- Mathematically guaranteed convergence
- Work offline and sync later
Disadvantages:
- Higher memory overhead (storing IDs for every character)
- More complex garbage collection
- Harder to implement undo/redo
Tools like Figma use CRDTs for their multiplayer editing. The choice between OT and CRDTs depends on your architecture — centralized (OT) vs. decentralized (CRDTs).
Building Your Own: A Minimal Mental Model
If you ever need to build collaborative features, here's the simplest mental model:
- Every change is an operation (insert, delete, format)
- Every operation has a version (what state of the document it was created against)
- The server is the authority on operation ordering
- Clients apply locally, send to server, transform incoming operations
The transformation logic for a plain text editor fits in about 100 lines of code. The production-grade implementation with formatting, presence, undo, and conflict resolution is closer to 100,000.
Why This Matters Beyond Google Docs
The principles behind OT show up everywhere in distributed systems:
- Git uses a form of operational transformation (three-way merge)
- Multiplayer games use similar state reconciliation techniques
- Distributed databases face the same concurrent modification problems
- Real-time dashboards need consistent state across multiple viewers
Understanding OT gives you a mental framework for any system where multiple actors modify shared state concurrently. That's most systems worth building.
This exploration draws from the original OT papers by Ellis and Gibbs (1989), Google's documentation on their collaborative editing infrastructure, and the CRDT research by Shapiro et al. The field continues to evolve, with hybrid approaches combining the best of both worlds.