Sweaty Imposter

Design Google Docs / Collaborative Editing

System DesignReal TimeShared StateSenior3 min readUpdated

Several people type into the same paragraph at once, and every copy has to end up identical without anyone's keystrokes vanishing. The design gives each document one server that orders its edits, and keeps an operation log that doubles as version history.

1 · Requirements

The Prompt

Let several people edit one document at once and see each other's cursors live, with every copy converging, offline edits, and full version history.

Functional

  • Several users edit one document at the same time
  • See other editors' cursors and selections live
  • Edit offline and merge on reconnect
  • Browse version history and restore an earlier version
  • Share with viewer, commenter, and editor roles

Non-Functional

  • A remote edit appears in under 200 ms
  • Every copy converges to the same text, and no acknowledged edit is lost
  • Large documents open in under 2 seconds

2 · Estimates

Drill This Phase First

Show the Answer and Estimates

Answer

About 4.3 TB a day

Half of 1M is 500,000 operations a second. At 100 bytes that is 50 MB a second, and times 86,400 seconds is about 4.3 TB a day.

Editors
1M concurrent editors at peak, each sending about 1 batched operation a second: 1M operations a second
Fan-Out
About 3 editors per active document, so each operation goes to 2 others: about 2M outbound messages a second
Op Log
Averaging 500,000 operations a second at 100 bytes: about 4.3 TB of operation log a day
Snapshots
1B documents at about 20 KB per snapshot: roughly 20 TB in object storage, plus older versions
Sockets
About 50,000 WebSockets per server: 20 servers at peak, and 40 to survive a zone failure
Latency
Under 200 ms for a remote edit: one hop to the document's server, a transform, and one hop out

3 · API

WebSocket /docs/:id/live → client sends { op, base_revision, client_seq }; server acks and broadcasts { op, revision, author }
GET /docs/:id → { snapshot, revision, ops_since_snapshot[] }
GET /docs/:id/revisions?before= → { revisions[{ revision, author, ts }] }
POST /docs/:id/restore { revision } → { revision } (applied as a new operation)
PUT /docs/:id/permissions { user_id, role: viewer|commenter|editor } → 204

Data Model

documents (SQL):
  doc_id (PK)       : uuid
  owner_id          : uuid
  title             : string
  head_revision     : bigint
  snapshot_revision : bigint
  snapshot_key      : string       object storage key

operations (Cassandra, partition = doc_id, cluster = revision):
  doc_id, revision (PK)
  author_id         : uuid
  client_seq        : int          dedupes resends
  op                : bytes        insert or delete at a position
  ts                : timestamp

permissions (SQL):
  doc_id, user_id (PK)
  role              : enum(viewer|commenter|editor)

4 · High-Level Design

An edit travels to the document's owner, which assigns the next revision, transforms it against any concurrent edits, appends it to the log, and broadcasts it to the other editors. Opening a document loads the latest snapshot plus the operations after it.

5 · Deep Dives

Operational Transformation

Every operation names the revision it was based on. When two edits based on revision 41 arrive, the server applies the first as revision 42 and transforms the second against it, shifting its position so both intents survive. One server ordering each document keeps the transform simple, and clients transform incoming operations against their own pending ones.

CRDTs as the Alternative

A CRDT gives every character a unique, ordered ID, so replicas converge in any order with no central server. That suits offline and peer-to-peer editing, at the cost of metadata that can be several times the size of the text. Server-backed editors such as Google Docs use OT; local-first editors lean on CRDTs.

Snapshots, History, and Offline

Replaying a year of operations on every open would be slow, so a worker writes a snapshot every 1,000 operations and the client loads the snapshot plus the tail. Version history is the operation log grouped by author and time. An offline client queues edits against its last revision and sends them on reconnect, where the server transforms them like any late edit.

6 · Wrap Up

Close with the next risks: one document with hundreds of live editors, comments anchored to text that moves, and a permission change that has to cut off an open socket.

The Short Version

Each document has one owning server, picked by consistent hashing, that orders edits with operational transformation (or a CRDT). Clients hold a WebSocket to that server. Operations append to a log keyed by (doc_id, revision), with snapshots in object storage.