SD System Design In Depth
0%
design system-designcollaborationcoordination

Design: a collaborative editor

Module 6.1: Infrastructure & Core Service Designs Updated Sep 18, 2026
📄 Cheat Sheet
Real-Time Collaboration Explained - System Design
Hello Interview Real-Time Collaboration Explained - System Design Watch on YouTube ↗

Focused explanation of OT vs CRDT and the server architecture for real-time editing (document sessions, broadcast, persistence), matching the scope of this lesson.

0:00 / --:--

The Concurrency Challenge in Real-Time Documents

When multiple users edit the same document concurrently (like Google Docs, Notion, or Figma), edits arrive out of order due to network latency. Without structured conflict resolution, character offsets shift and documents diverge into corrupted states.

The Two Core Paradigms: OT vs. CRDT

flowchart TD Approach{"Concurrency Resolution"} Approach --> OT["Operational Transformation: OT"] Approach --> CRDT["Conflict-free Replicated Data Types: CRDT"] OT --> CentralServer["Often uses an authoritative server: Google Docs"] CRDT --> P2P["Peer-to-Peer & Decentralized Capable: Yjs, Automerge"]

Operational Transformation (OT)

OT transforms edit operations (Insert, Delete, Retain) against concurrent operations based on character indices:

  • If User A inserts character 'x' at position 2, and User B concurrently inserts 'y' at position 0, User A's operation must be transformed to position 3 to account for User B's insertion.
  • Tradeoff: Many production OT systems use an authoritative server to order operations and simplify recovery, but decentralized OT algorithms also exist. Correct transformation, history, acknowledgements, and reconnect behavior remain complex.

CRDTs (Conflict-free Replicated Data Types)

Modern collaborative systems increasingly adopt CRDTs (e.g., RGA, Yjs, Automerge):

  • Sequence CRDTs use stable element identities or another mergeable ordering representation; not every CRDT uses fractional positions or stores one identifier per visible character.
  • Under the algorithm's delivery and causality assumptions, replicas can apply concurrent operations in different orders and converge without a central serialization point. Transport, persistence, access control, and garbage collection still need coordination.

Worked example: one OT transform

The document is abc. At the same moment, Alice inserts x at index 2 (to get abxc) and Bob deletes index 0 (to get bc). The server receives Bob's operation first.

  • The server applies Bob's delete: bc.
  • Alice's insert at 2 was based on the old document. Bob deleted a character before index 2, so the transform shifts Alice's index down by one, to insert(x, 1), giving bxc.
  • Alice's client receives Bob's delete at 0. Her own insert at 2 is after it, so she applies delete(0) to abxc and also gets bxc. Both sides converge.

A CRDT reaches the same result differently. Alice's x is recorded as "after the element with ID b", so deleting a does not affect where it goes.

OT vs CRDT

AspectOT (Google Docs, CKEditor, ShareDB)CRDT (Yjs, Automerge, Loro)
OrderingUsually a central server orders operationsNo central ordering needed; merges commute
Offline editingPossible but hard after long divergenceNatural; merge on reconnect
Metadata overheadSmall (just the operations)IDs per element; modern encodings (Yjs, Automerge 2) compress runs well
Correctness riskTransform functions are notoriously hard to get rightInterleaving and intent anomalies (Kleppmann)
Rich text and structureMature in production editorsImproving (Peritext, Yjs types)

Figma, often cited as a CRDT example, actually uses a server-authoritative model inspired by CRDTs. Each object property is last-writer-wins, and the server decides the order. It is not a peer-to-peer text CRDT.

Service architecture and numbers

flowchart LR C1["Editor client A"] <-->|"WebSocket"| S["Doc session server, sticky by doc_id"] C2["Editor client B"] <-->|"WebSocket"| S S --> L[("Append-only op log")] S --> P[("Snapshot store, every N ops")] S --> R["Presence and cursors, not persisted"]
  • Route all clients of one document to the same session server (consistent hashing on doc_id). The document state then lives in one process's memory, and ordering is local to that process.
  • With 50 concurrent editors each sending about 5 operations per second, the server receives 250 operations per second and must broadcast about 12,500 messages per second. Batch outgoing operations every 30 to 50 ms to cut message counts.
  • Snapshot every 500 to 1,000 operations, so opening a document loads the latest snapshot plus a short tail of operations instead of the entire history.
  • Throttle cursor and selection updates (for example to 10 per second) and never store them; they are ephemeral.
Check yourself Question 1 of 3
Transforming an insert apply
From: Worked example: one OT transform

The document is abcd. Concurrently, Alice inserts x at index 3 (giving abcxd) and Bob deletes index 1 (giving acd). The server applies Bob's delete first. What must Alice's operation become?

CRDT PN-Counter
Eventual Consistency
Node A
0
State: P[0,0], N[0,0]
Node B
0
State: P[0,0], N[0,0]

Key Takeaways

Character offset coordinates are fragile under concurrent editing; they require transformation or fractional identifiers.
Many OT deployments use a centralized coordinator, but centralization is an architectural choice rather than a mathematical requirement of all OT algorithms.
CRDTs assign immutable IDs to every token and converge deterministically in peer-to-peer or server topologies.
Use WebSockets for real-time operation transport and snapshot document states periodically to compact mutation logs.
Was this lesson helpful? Spot an issue or have a suggestion? Let us know on GitHub.
Report an issue