41. Collaborative Editing (Google Docs / Office 365)
Business context. Productivity suite. Outcomes are real-time collaboration that feels instant (a key reason teams pick the product), never losing a user's work, and enterprise needs (permissions, version history, compliance).
Requirements. Many users editing the same document concurrently; see each other's cursors; offline edits that merge later; version history; sharing and permissions; comments. Latency: local edits apply instantly, and remote edits appear in < 200 ms.
Concurrency approaches.
| Operational Transformation (OT) | CRDTs | |
|---|---|---|
| Idea | Transform concurrent operations against each other so they converge | Data structure designed so concurrent ops commute |
| Server | Central server orders operations (simplifies OT a lot) | Can be peer-to-peer; works offline naturally |
| Used by | Google Docs (server-ordered OT) | Many newer editors (Yjs, Automerge); Figma uses a server-authoritative, CRDT-inspired model |
| Costs | Transformation functions are notoriously hard to get right | Metadata overhead (tombstones, IDs per character); needs compaction |
Design (server-ordered).
Clients ◀═ WebSocket ═▶ Collaboration gateway ─▶ Document session server
(one authoritative owner per active doc, chosen by consistent hashing / lease-based assignment)
- receives ops with client revision number
- transforms against ops the client hasn't seen, assigns the next revision, appends to op log
- broadcasts to all session participants; acks the author
Op log (durable, per doc) ─▶ periodic snapshots (doc state at revision N) ─▶ object storage
Load doc = latest snapshot + replay ops since snapshot
Presence/cursors: ephemeral, broadcast only, never persisted
Permissions: ACL service (Zanzibar-like relationship tuples) checked at session join and on share changes
Deep dives.
- One owner per document makes ordering trivial and lets the session server keep the document in memory. You need lease-based ownership with fencing (§19.3) so two servers never both think they own a document after a network partition.
- Durability: an op is acked to the author only after it's durably appended. The client keeps unacked ops locally and resends them after reconnecting (idempotent op IDs).
- Hot documents: a company-wide doc with 2,000 viewers. Separate the editors (full op stream) from viewers (throttled, batched updates, or snapshots).
- Version history: derived from the op log plus snapshots. Retention policies apply.
Strategic lens. Enterprise requirements (data residency per tenant, customer-managed keys, eDiscovery over document history, DLP scanning) are often the deciding factor for large customers. The design has to keep the real-time path fast while feeding the compliance plane asynchronously.
🏗️ Flow: two concurrent edits, server-ordered OT.
Doc text: "abc" (rev 10)
Alice (at rev 10): insert "X" at 1 → "aXbc"
Bob (at rev 10): delete at 2 ("c") → "ab"
Server receives Alice first → rev 11 = ins(1,"X") → broadcast
Server receives Bob's del(2) based on rev 10 → transform against ins(1,"X") → del(3) → rev 12
Bob's client: receives ins(1,"X") while having pending del(2) → transforms the incoming op
against its pending op → both converge to "aXb"
🌍 How it's built in production.
- Google Docs: operational transformation with a central server that orders operations (a descendant of the Jupiter collaboration system). Every change is stored as an operation, which also powers revision history.
- Figma multiplayer ("How Figma's multiplayer technology works", 2019): one server process per open document holds its state; the server is authoritative. Conflicts resolve per property with last-writer-wins, and object trees use parent links plus fractional indexing for ordering. CRDT-inspired, but simpler, because a central server exists.
- Microsoft Fluid Framework (behind Loop components and parts of Office collaboration): a lightweight total-order broadcast service stamps sequence numbers on ops, and clients run distributed data structures that merge deterministically. Server costs are low because the server doesn't interpret ops.
- Yjs and Automerge: CRDT libraries for offline-first and peer-to-peer editing.
⚠️ Corner cases.
- Undo in a collaborative editor: undo must invert my last operation, transformed against everyone else's since then, not restore the old document state.
- Long offline divergence: a user edits offline for a week. The merge can be correct but semantically surprising. Show the changes, keep version history, and allow conflict review for structured content.
- Huge pastes: a 5 MB paste becomes one op that stalls everyone. Chunk it, and rate-limit the broadcast.
- Permission revoked mid-session: the server must close the user's session and stop sending ops immediately (the "new enemy" problem again, §17.2).
- Session server crash: a new owner loads the snapshot plus the op-log tail. Clients resend unacked ops by op ID (idempotent), and the fencing token prevents the old server from appending.
- Document model migrations: new client features add node types old clients don't understand. Use forward-compatible schemas, unknown-node preservation, and minimum client versions for editing.