Question Breakdowns
Collaborative Docs
A worked system design: let many people edit one document simultaneously and converge to the same result (think Google Docs). Concurrent edits, OT vs CRDTs, real-time sync, and persistence.
Collaborative docs let multiple people edit the same document at the same time and see each other's changes live, with everyone's view converging to the same final text no matter the order edits arrive. The hard, distinctive problem is concurrent editing: if two people type at the same position simultaneously, how do all clients end up identical without losing anyone's keystrokes? That question — and its two classic answers, OT and CRDTs — is the heart of the design. It builds on Real-time Updates.
1. Requirements
Functional:
- Multiple users edit one document concurrently; edits appear live to all.
- Everyone converges to the same document state regardless of edit timing.
- Persist the document; show presence/cursors (nice-to-have).
Non-functional:
- Convergence — all clients reach identical state; no lost edits. Non-negotiable.
- Low latency — local edits feel instant; remote edits appear within moments.
- Resilient — handle disconnects/reconnects and reconcile offline edits.
- Scale — many docs, each with a bounded set of concurrent editors.
2. Why naive sync fails
"Send the whole document on every keystroke" doesn't converge: two users editing from the same base overwrite each other, and last-write-wins loses edits. You can't send positions blindly either — if I insert "X" at index 5 while you delete index 2, my index 5 now points somewhere else. Concurrent edits must be transformed against each other so they still mean the right thing after reordering. That's the core.
3. The two approaches: OT vs CRDT
Operational Transformation (OT). Represent edits as operations (insert "X" at 5, delete at 2). When a concurrent op arrives, transform it against ops it didn't see, adjusting indices so intent is preserved. A central server orders ops and transforms them, broadcasting the canonical sequence. Powerful and compact, but the transformation functions are famously tricky to get right. (This is the classic Google Docs approach.)
CRDTs (Conflict-free Replicated Data Types). Give every character a unique, stable identifier (not a shifting index) with an ordering, so inserts and deletes commute — apply concurrent edits in any order and you converge, by construction, no central transformation needed. Simpler to reason about and peer-to-peer friendly; the cost is per-character metadata (mitigated by modern implementations).
OT: ops + server transforms against concurrent ops → canonical order
CRDT: each char has a unique id → edits commute → converge anywhere, any order| OT | CRDT | |
|---|---|---|
| Needs central server | Typically yes | No (P2P-capable) |
| Core difficulty | Transform functions | Per-char metadata |
| Convergence | Via transformation | By construction |
Either is a valid interview answer — what matters is explaining why shifting indices break and how your choice makes concurrent edits converge.
4. Real-time sync architecture
A document editing session runs over a real-time connection: each client holds a WebSocket to a server that owns that document's session. Edits flow to the server (which, for OT, orders and transforms them), then broadcast to the other editors:
editor → op → doc session server → (order/transform) → broadcast to co-editors
local edit applied immediately (optimistic); reconciled when server's version returnsClients apply their own edits optimistically for instant feedback, then reconcile with the server's authoritative sequence. All editors of one doc are routed to the same session server so there's a single ordering point (route by doc_id).
5. Persistence
The live session holds the document in memory for speed; durability comes from:
- Op log: append every operation to a durable log — the document is the replay of its ops (event sourcing, like the Stock Trading book). Enables history, undo, and recovery.
- Snapshots: periodically persist the materialized document so recovery replays only ops since the last snapshot, not all of history.
6. Deep dives
- Offline/reconnect: an editor offline accumulates ops locally and syncs on reconnect — OT transforms them against what it missed; CRDTs merge naturally. This is where CRDTs shine.
- Presence/cursors: ephemeral, broadcast over the same channel, not persisted.
- Large docs / scale: one session server per doc bounds concurrency per doc; scale across docs by routing
doc_idto servers. - Rich content: formatting/tables extend the op model but the convergence principle is identical.
What to emphasise
Explain why indices break, then name OT or CRDT and the optimistic real-time loop:
"The core problem is concurrent edits: a plain index-based edit breaks when someone else's insert or delete shifts positions, and last-write-wins loses keystrokes. So edits must be transformed to preserve intent — either Operational Transformation, where a central server orders ops and transforms concurrent ones against each other, or CRDTs, where each character has a stable unique id so edits commute and converge in any order. All editors of a doc connect over WebSockets to one session server that provides a single ordering point; clients apply edits optimistically for instant feedback and reconcile with the server's sequence. Durability is an append-only op log plus periodic snapshots, which also gives history and clean reconnect handling."
Next up: Payment System — moving money correctly.
