#27 Operational Transformation
Collaborative Docs (Notion)
Let several people edit the same page at once and see each other's changes immediately, with everyone ending on identical content.
What is being asked
Design real-time collaborative editing for a block-based document tool like Notion. Two users type in the same paragraph at the same moment; both must converge to the same text without losing either edit.
Requirements
Functional
- Concurrent editing with live cursors and presence.
- Offline edits that merge on reconnect.
- Version history and undo.
Non-functional
- Edits appear to others within about 100 ms.
- All clients converge to the same document.
- Documents range from a paragraph to very long pages.
Design
- Each client applies its own edit instantly and sends it as an operation, tagged with the document version it was based on.
- All clients of one document connect to the same session server, which puts operations in a single order.
- If an operation was based on an older version, the server transforms it against the operations it missed (operational transformation), then applies it, assigns the next version and broadcasts it.
- Clients transform their own pending operations against what arrives, so every copy converges.
- Operations are appended to a log; periodic snapshots keep loading fast.
Key decisions and trade-offs
- Operational transformation or CRDTs. OT needs a central server to order operations and is compact. CRDTs merge without a central authority and suit offline and peer-to-peer use, at the cost of extra metadata per character.
- Block-level structure. Treating a page as a tree of blocks limits most conflicts to within one block and makes moves and nesting explicit operations.
- One server per document. Routing all editors of a document to one process makes ordering trivial; it needs sticky routing and fast failover with replay from the log.
- Presence (cursors, who is here) is ephemeral and is sent on a separate, lossy channel.
Follow-up questions
- What happens when the session server for a busy document crashes?
- How would you merge a week of offline edits?
- How do you implement undo when others have edited in between?
- How do permissions apply when a block is moved into a private page?