Design a Collaborative Editor — Real-Time Sync Like Google Docs
The hardest real-time problem#
Building a collaborative editor where multiple users type simultaneously without losing changes or seeing glitches is one of the hardest distributed systems problems.
Google Docs, Notion, and Figma each solve it differently. Understanding the approaches teaches you real-time sync, conflict resolution, and distributed state management.
The fundamental challenge#
Two users type at the same position simultaneously:
Document: "Hello World"
User A: Insert "X" at position 5 → "HelloX World"
User B: Insert "Y" at position 5 → "HelloY World"
Both operations arrive at the server.
What should the final document be?
"HelloXY World"? "HelloYX World"?
Both users must see the same result.
Approach 1: Operational Transformation (OT)#
Used by Google Docs. Transform operations against each other so they produce the same result regardless of order.
How it works:
- Each edit is an operation:
Insert("X", pos=5)orDelete(pos=3) - When two operations conflict, transform one against the other
- Transform adjusts positions to account for the other operation
Example:
User A: Insert("X", 5)
User B: Insert("Y", 5)
Transform B against A:
B was at position 5, but A inserted before it
B becomes: Insert("Y", 6)
Result: "HelloXY World" (deterministic)
Pros: Well-understood, proven at Google scale Cons: Complex transformation rules, centralized server required, hard to implement correctly
Approach 2: CRDTs (Conflict-Free Replicated Data Types)#
Used by Figma, Notion (partially), and Yjs. Data structures that can be merged without conflicts by design.
How it works:
- Each character has a unique ID (user + logical timestamp)
- Characters are ordered by their IDs, not positions
- Insertions place new characters between existing ones
- Deletions mark characters as tombstones (not removed)
Popular CRDT libraries:
- Yjs — Most popular, supports text, arrays, maps
- Automerge — Rust-based, good for structured data
- Diamond Types — Optimized for text editing
Pros: No central server needed, works offline, peer-to-peer capable Cons: Tombstones accumulate (memory), eventual consistency only
Architecture#
Server-side (OT approach)#
Client A → WebSocket → Server (single source of truth)
Client B → WebSocket ↗ ↓ transform + broadcast
Client C → WebSocket ↗ ↓
All clients get transformed operations
Peer-to-peer (CRDT approach)#
Client A ←→ Sync Server ←→ Client B
←→ ←→ Client C
Each client has full document state
Server relays, doesn't transform
Cursor presence#
Showing where other users are typing:
- Each client sends cursor position updates (throttled to 50ms)
- Server broadcasts cursor positions to all other clients
- Client renders colored cursors with user name labels
Optimization: Don't send cursor updates on every keystroke — throttle or debounce, and batch with document operations.
Key components#
Document model: Tree of blocks (paragraphs, headings, lists) containing text runs with formatting.
Operation log: Append-only log of all operations for undo/redo and time travel.
Version vector: Track which operations each client has seen to detect gaps.
Awareness protocol: Cursor positions, selections, user online status.
Persistence: Periodically snapshot the document state to avoid replaying the entire operation history on load.
Scaling considerations#
| Challenge | Solution |
|---|---|
| WebSocket connections | Horizontal scaling with sticky sessions or shared state |
| Large documents | Lazy load blocks, only sync visible sections |
| Operation history growth | Periodic snapshots, garbage collect old ops |
| Offline editing | CRDT enables full offline support, sync on reconnect |
| Permission changes | Real-time permission checks on each operation |
Visualize your collaborative editor#
See how real-time sync, WebSockets, and document storage connect — try Codelit to generate an interactive diagram of a collaborative editor.
Key takeaways#
- OT is proven at scale (Google Docs) but requires a central server
- CRDTs enable offline + peer-to-peer but use more memory
- Cursor presence needs throttled WebSocket updates
- Yjs is the go-to CRDT library for most use cases
- Snapshot periodically to avoid replaying entire history
- Both approaches converge — the document ends up the same regardless of operation order
Explore the Notion architecture interactively
Try it →Try these templates
Uber Real-Time Location System
Handles 5M+ GPS pings per second using H3 hexagonal geospatial indexing.
6 componentsInstagram-like Photo Sharing Platform
Full-stack social media platform with image processing, feeds, and real-time notifications.
12 componentsReal-Time Collaborative Editor
Notion-like document editor with real-time collaboration, conflict resolution, and rich media.
9 componentsContinue learning
Go deeper on system design
As an Amazon Associate I earn from qualifying purchases. Codelit may receive a commission at no extra cost to you.
Building Microservices
Sam Newman · 2021
600 pages on splitting a monolith: service boundaries, data decomposition, migration order.
Release It!
Michael T. Nygard · 2018
Post-mortems of real outages, then the stability patterns (circuit breaker, bulkhead) that stop them.
4.6 (501)#4 in Client-Server Networking SystemsElements of Programming Interviews in Python
Adnan Aziz, Tsung-Hsien Lee, Amit Prakash · 2016
250 problems worked in runnable Python, with variants showing how a follow-up question moves.
The Staff Engineer's Path
Tanya Reilly · 2022
What the job becomes past senior: scope, sponsorship, and writing that moves a technical decision.