Design Google Docs
Collaborative editing is several people changing one document at the same time, with each change shown to the others at once. Google Docs is the interview name for this problem.
Clarify the ask
The first questions fix what editors must be able to do.
Editors type in the same document during the same moments. Each editor sees the others' changes appear without reloading.
An editor is a person with permission to change the document. A viewer is a person who can read but not change it.
The document also keeps its history. Any earlier version can be viewed and restored.
Estimate the scale
The estimate uses the figures fixed for this problem.
The text of a long document is about 100 KB. The document itself is small enough to hold in memory with ease.
One edit operation is about 100 bytes on the wire. An operation is one small change, such as one inserted letter.
An active document sees 1,000 edits a day from its editors.
1,000 edits × 100 bytes = 100,000 bytes of edit log a day. That is 100 KB of log per active document per day.
Name the parts
The editing client is the program in the browser or app. It sends each operation and applies operations from others.
A session server holds each open document. It orders the operations and sends them to every editor.
Document storage holds the text and the edit log.
Collaborative editing is several people changing one document at the same time. The parts exist to keep those changes in one agreed order.
Name the hard parts
Two editors can change the same sentence at the same moment. Both changes must survive and land in sensible places.
Editors also work at different speeds and on weak connections. A late operation must still fit the current text.
History grows with every edit. The design must rebuild old versions without slowing current editing.
Concurrency, the two merging methods, presence, storage, and scale each answer one of these hard parts.
What success looks like
Success means every editor ends with the same text. Two screens showing different final text would be a failure.
Success also means changes feel instant to the typist. The editor's own letter appears at once, before any server reply.
Correctness comes before cleverness here. A merged document that loses a sentence has failed, however fast it felt.
The high-level design
The high-level design fixes one shared order of operations for each document.
An operation is one small change to the text. Inserting a character and deleting a character are the two basic operations.
An insert operation carries a place, a character, and an operation mark.
A delete operation carries a place and an operation mark.
The client shows the editor's own operation at once. It then sends the operation to the session server.
The session server gives the operation the next sequence number for that document. A sequence number is a position in one shared order.
The server then broadcasts the operation to the other editors. Broadcast here means sending one message to every other editor of the document.
Why positions move
An operation names a place in the text it was written against. That text can change before the operation arrives anywhere else.
Suppose one editor inserts a word at the start of a sentence. Every later place in that sentence shifts by the length of that word.
A second editor's operation still names the old place. Applied blindly, it would land in the wrong spot.
Such operations must be adjusted before they are applied elsewhere. The shared order is what they are adjusted against.
The broadcast arithmetic
Take 50 editors in one document at the same time. That crowd is a stated example, not a typical document.
One edit must reach the other 49 editors. The author already has the edit on screen.
50 editors − 1 author = 49 copies sent per edit.
49 copies × 100 bytes per operation = 4,900 bytes sent per edit.
The number stays small because operations are tiny. The count of editors, not the document size, drives this cost.
Keeping the order safe
Each operation carries a unique mark from its client. The mark lets the server spot the same operation sent twice.
A retry after a weak connection can deliver an operation twice. The server applies it once and ignores the repeat, which is idempotency.
The server confirms each operation back to its author. The confirmation carries the operation's sequence number.
An editor who misses an operation asks for the missing range. The server resends operations by their sequence numbers.
Where concurrency breaks
The session server for a document is a single point of failure for that document. If it stops, editing pauses while a replacement takes over.
The replacement rebuilds the document from storage. Editors then reconnect and resend any unconfirmed operations.
Concurrency is two or more editors changing one document during the same moments. One shared order is what keeps that crowd editing one text, not many.
A deep dive on merging edits
Merging edits is where concurrent operations become one shared text.
Operational transformation is often shortened to OT. CRDT names the rival method.
Both methods solve the same problem. Concurrent operations must merge into one text that every screen shares.
How operational transformation works
The server holds the current version of the document. Each incoming operation names the version it was written against.
An operation written against the current version applies as it stands. Most operations take this simple path.
An operation written against an older version is transformed first. The server adjusts its place past each operation applied since that version.
Suppose an earlier operation inserted a word before the target place. The transformed operation moves its place forward by that word.
Operational transformation adjusts an edit made against an older version so it fits the current version. The server and its shared order make that adjustment possible.
How a CRDT works
A CRDT is a data shape where each change carries a unique mark, so copies can merge in any order and reach the same result. The name stands for conflict-free replicated data type.
In a CRDT document, each character carries its own mark. The mark names the editor who typed it and a counter for that editor.
A delete does not erase the character at once. It marks the character as removed, and views skip marked characters.
Two copies exchange operations in any order. The marks sort the characters the same way on every copy.
No central order is needed. That freedom is the main strength of the CRDT method.
The CRDT cost arithmetic
The marks are not free. The comparison assumes a mark adds 20 bytes to each operation.
100 bytes per operation + 20 bytes of mark = 120 bytes per operation.
An active document sees 1,000 edits a day. 1,000 edits × 120 bytes = 120 KB of edit log a day under the CRDT method.
The same log under OT is 100 KB a day. The gap is small per document and grows across many documents.
Removed characters also linger as marks in the text. A long-lived document carries that history inside its live data.
Choosing between them
Operational transformation needs a central order, and a CRDT does not.
Working fully offline is harder under operational transformation and easier under a CRDT.
The extra data per edit is small under operational transformation and larger under a CRDT.
This design chooses operational transformation. A session server already orders operations for every open document.
OT keeps operations small and the live text clean. Its weakness is the central server that every edit passes through.
A CRDT suits tools that must merge after long offline periods with no server. That is not the main shape of this problem.
Either method can be correct when built carefully. The choice here follows the shape of the service, not fashion.
Design the data side
Presence and storage are the data side of the design.
Presence is the signal that shows who is in a document and where each person is working. It covers the editor list and each cursor place.
A cursor place is the spot in the text where one editor is typing. Other editors see it as a coloured marker with a name.
Presence is helpful and disposable. Losing it for a moment harms nothing, unlike losing an edit.
How presence flows
Each open client sends a small presence update when the cursor moves. It also sends a heartbeat, a small still-here message.
This design sets the presence heartbeat at one update every 5 seconds. That interval is a stated choice of this design.
60 seconds ÷ 5 seconds = 12 presence updates per editor per minute.
A document with 50 editors sends 50 updates every 5 seconds. That is 10 presence updates per second for that document.
A presence record expires when its heartbeats stop. The editor then leaves the shown list without any closing message.
The storage shape
The document record holds the name, the owner, and the permissions. Permissions say who may read and who may edit.
The operation log holds every edit in sequence order. It is the complete history of the document.
A snapshot is a saved copy of the full text at one moment. Snapshots make loading and history practical.
Loading a document reads the latest snapshot first. It then applies the operations saved after that snapshot.
A presence record holds the editor, the cursor place, and the last seen time.
The snapshot arithmetic
The operation log grows by 100 KB a day for an active document. That figure comes from 1,000 edits at 100 bytes each.
This design takes a snapshot every 100 edits, a stated choice. 1,000 edits ÷ 100 edits = 10 snapshots a day.
Each snapshot holds the full text of about 100 KB. 10 snapshots × 100 KB = 1,000 KB, which is 1 MB of snapshots a day.
Old snapshots can be thinned out over time. Keeping every snapshot forever would cost far more than the log itself.
Where presence and storage break
Presence reveals who is working and when. The design shows presence only to people with access to the document.
A stale cursor marker can point at text that has moved. Clients treat cursor places as hints, not as exact truth.
A damaged log breaks history for one document. The log therefore gets copies in more than one data center, like the metadata in file sync.
Estimate the service scale
The whole service has its own scale estimate, separate from the scale of one document.
The service estimate assumes 10,000,000 active documents a day across the service. That figure is a stated assumption of this design.
Each active document sees 1,000 edits a day. 10,000,000 documents × 1,000 edits = 10,000,000,000 edits a day.
10,000,000,000 edits ÷ 86,400 seconds = 115,741 edits per second on average.
No single document is huge. The challenge is the count of documents and edits, not the size of one text.
Shard by document
A shard is one part of a split data store. This design shards the documents, using the document itself as the shard key.
Every operation for one document lands on the same shard. Its ordered log stays in one place, which the ordering design requires.
A hot document is the main risk. A document edited by a huge crowd can overload its one shard.
Most documents stay quiet, so the load spreads well. The hot case is handled by giving that document a dedicated server while it stays hot.
The history arithmetic
One active document keeps 1,000 edits a day. 1,000 edits × 365 days = 365,000 edits kept in a year.
Each edit takes about 100 bytes in the log. 365,000 edits × 100 bytes = 36.5 MB of log for one document in a year.
History is the saved record of every edit. At these sizes, keeping full history per document is affordable.
Rebuilding an old version reads the nearest snapshot. It then replays the operations after that snapshot, in order.
Keeping history practical
Log compaction folds old operations into a snapshot. The snapshot then replaces the long early log.
Named versions help editors most. A named version is a snapshot an editor marked, such as a finished draft.
Deleted documents keep their history for a set recovery period. After that period, the text, log, and snapshots are removed.
Search across documents is a neighbouring problem. This design stores the text so a search service can index it, and designs no index here.
Where scale breaks
A single celebrity document can break the quiet-document assumption. Many editors at once stress ordering, broadcast, and presence together.
The design answers with limits per document. A document past its editor limit admits further people as viewers.
Cross-region editing adds the ocean round trip of about 150 milliseconds to late operations. The home region of a document is therefore the region of its owner.
Evaluate the design
Each choice in the design follows from one central bet.
The design's core bet is a central session server per document. Most other choices follow from that bet.
Each choice states both sides plainly. Each verdict answers a problem named in the ask.
Speed against strict order
Strict ordering makes every screen agree. It also forces each operation through the session server.
The client hides that cost by showing the typist's own edit at once. The server order catches up a moment later.
A busy document shows the limit of broadcast. With 100 editors in one document, one edit reaches 99 other editors.
100 editors − 1 author = 99 copies per edit. 99 copies × 100 bytes = 9,900 bytes sent per edit.
That cost is acceptable for real editing crowds. It also explains the per-document editor limit.
OT against CRDT
Operational transformation keeps operations at about 100 bytes and the live text free of marks. It needs the central server this design already runs.
A CRDT would remove that central need. It would charge about 120 bytes per operation, plus marks kept in the text.
For long offline work with no server, the balance would flip. For this service shape, the verdict stays with operational transformation.
History against storage
Keeping every edit makes history complete and restore simple. It also makes storage grow every day, forever.
Snapshots and compaction keep that growth practical. Old operations fold into snapshots instead of staying as long logs.
Presence sits at the opposite extreme. It is stored barely at all, expires in seconds, and nobody misses its old values.
The wrap-up
One shared order, applied by one session server, is the heart of the design. Operational transformation makes late edits fit that order.
The main weakness is the hot document. A huge editing crowd strains ordering, broadcast, and presence at the same time.
Collaborative editing is several people changing one document at the same time, ending with the same text. This design keeps that promise, and that is the verdict.
The ask in short
| Item | Working figure |
|---|---|
| Long document text | 100 KB |
| One edit operation | 100 bytes |
| Edits on an active document per day | 1,000 |
| Edit log per active document per day | 100 KB |
Exercise
Why can presence be loose while the text order must stay strict?