Day 48: Design: Collaborative Document Editor (Google Docs/Figma)
Understand the two dominant conflict-resolution models for real-time collaborative editing — Operational Transformation and CRDTs — and their tradeoffs.
Study
Concepts
The core problem: concurrent edits to the same document
Two users type in the same paragraph at the same time. Without a resolution strategy, applying both edits naively (e.g. by raw text-insert-at-index) corrupts the document, because the second edit's index was computed against a document state that no longer exists once the first edit is applied. Real-time collaborative editors need a way to transform or merge concurrent operations so every client converges to the SAME final document, regardless of the order operations arrive in.
Operational Transformation (OT) — used historically by Google Docs — transforms an incoming remote operation against any local operations that happened concurrently, adjusting its index/position so it applies correctly on top of local changes; it requires a central server to serialize and broadcast a canonical operation order, and the transform functions are notoriously tricky to get exactly right for complex operations.
CRDTs: convergence without a central authority
A CRDT (Conflict-free Replicated Data Type) is a data structure specifically designed so that ANY set of concurrent operations, applied in ANY order, on ANY replica, converges to the same final state — mathematically, by construction, without needing a central server to decide ordering. For text editing, this typically means each character (or block) gets a unique, ordered identifier (e.g. via a technique like RGA or Logoot) so insertions/deletions can be applied locally and merged from any peer without conflicts, enabling true peer-to-peer or offline-then-sync collaborative editing (Yjs and Automerge are the dominant real-world CRDT libraries).
The practical tradeoff: OT is generally more compact on the wire and mature in battle-tested systems, but is server-dependent and hard to implement correctly from scratch; CRDTs are more resilient to offline/peer-to-peer scenarios and easier to reason about correctness-wise, but historically carried more memory/metadata overhead per character (modern CRDT libraries like Yjs have optimized this substantially).
See It
Visualizations
Visualization
Operational Transformation vs CRDTs
| OT | CRDT | |
|---|---|---|
| Requires central server | Yes — to serialize operation order | No — convergence by construction |
| Works offline / peer-to-peer | Poorly — needs server round trip to transform | Naturally — merge whenever peers reconnect |
| Implementation difficulty | High — transform functions are notoriously tricky | Moderate — but subtle correctness details still matter |
| Real-world examples | Google Docs (historically) | Figma (custom CRDT-like), Yjs, Automerge |
| Per-character overhead | Low | Historically higher, much improved in modern libs |
Visualization
A CRDT-based editor architecture (Yjs-style)
Build It
Code Examples
A minimal collaborative text editor with Yjs
import * as Y from 'yjs';
import { WebsocketProvider } from 'y-websocket';
const ydoc = new Y.Doc();
const provider = new WebsocketProvider('wss://sync.example.com', 'doc-room-1', ydoc);
const ytext = ydoc.getText('content'); // a CRDT-backed shared text type
function CollaborativeEditor() {
const [text, setText] = useState(ytext.toString());
useEffect(() => {
const observer = () => setText(ytext.toString()); // fires on ANY remote or local change
ytext.observe(observer);
return () => ytext.unobserve(observer);
}, []);
function handleChange(e) {
const newValue = e.target.value;
// Applying a diff (not a full replace) lets Yjs merge this
// correctly against concurrent remote edits automatically.
ydoc.transact(() => {
ytext.delete(0, ytext.length);
ytext.insert(0, newValue);
});
}
return <textarea value={text} onChange={handleChange} />;
}
// Two browser tabs pointed at the same room converge automatically —
// no server-side transform logic required, and it survives brief disconnects.Remember
Key Takeaways
- Naive concurrent text edits corrupt a document — real-time collaboration requires OT or CRDTs to guarantee convergence.
- OT transforms incoming operations against concurrent local ones; it requires a central server to establish a canonical order.
- CRDTs are data structures designed so ANY merge order converges to the same state — no central authority required.
- CRDTs handle offline-then-reconnect and peer-to-peer scenarios far more naturally than OT.
- Yjs and Automerge are the production-grade CRDT libraries most teams should reach for rather than implementing OT/CRDT from scratch.
Do It
Practice
- 1Build the two-tab Yjs demo above and prove convergence by editing simultaneously in both tabs while briefly disabling network in one.
- 2Explain in your own words why naive "insert at index N" breaks under concurrent edits, with a concrete two-user example.
- 3Research and summarize (2-3 sentences) how Figma's multiplayer technology differs from a textbook CRDT for text.