Skip to content
AI360Xpert

Collaborative Editor

Intermediate

Overview

A collaborative editor lets multiple users simultaneously view and edit the same document in real time, with every participant seeing changes within milliseconds. The central challenge is conflict resolution: when two users type at the same position at the same time, the system must converge to the same document state on every client without losing either user's work.

High-level architecture for Collaborative Editor
High-level architecture for Collaborative Editor

Functional Requirements

  • Create, open, and edit text documents.
  • Multiple users edit the same document concurrently in real time.
  • All users converge to the same document state (no lost edits).
  • Show each collaborator's cursor position and selection live.
  • Persist documents durably with version history and undo support.

Non-Functional Requirements

  • Low latency: local edits must appear instantly; remote edits should arrive within ~200 ms.
  • Consistency: all clients must converge to the same document after all operations propagate (strong eventual consistency).
  • Availability: the editor should remain usable during brief network interruptions (offline editing, sync on reconnect).
  • Scale: support documents with up to 100 concurrent editors and millions of documents total.

Capacity Estimation

Assume 10M active documents/day, average 3 concurrent editors per document, and 5 operations/sec per user (keystrokes, selections).

  • Concurrent connections: 10M x 3 = 30M WebSocket connections (spread across the day, peak ~5M concurrent).
  • Operations/sec: 5M concurrent users x 5 ops/sec = 25M ops/sec at peak — this is the dominant load and is handled peer-to-peer per document session, not globally.
  • Per-document session load: 3 users x 5 ops/sec = 15 ops/sec per document — easily handled by a single session server.
  • Storage: a document ~ 50 KB; operation log ~ 10x document size over its lifetime. 10M docs x 500 KB = 5 TB/day of operation history, heavily compactable.

High-Level Architecture

Clients connect via WebSockets to a routing layer, which maps each doc_id to a single stateful Session Server. That session server is the central authority for that document, responsible for ordering operations, resolving conflicts (via OT or CRDTs), broadcasting changes to all other connected clients, and periodically snapshotting the document state to a durable database.

Data Model

EntityFields / SchemaStorage Choice
document
doc_id (PK), title, owner_id, current_snapshot, version, created_at
Relational or document store (PostgreSQL/MongoDB)
operation
doc_id (partition), seq_id (sort), user_id, op_type, position, content, ts
Append-only log (Cassandra or DynamoDB)
snapshot
doc_id, version, content, created_at
Blob / document store (periodic compaction)
session
doc_id, node_id, active_users, created_at
In-memory registry (Redis) with TTL
presence
doc_id, user_id, cursor_pos, selection, color
In-memory on the Session Server, ephemeral

Detailed Design

The Core Problem: Conflict Resolution

Two proven approaches exist to handle conflicts without locking the document:

  • Operational Transformation (OT): The server acts as the single source of truth. It receives operations (e.g., "Insert 'A' at index 5"), transforms them if another operation happened concurrently, and broadcasts the transformed operation. This is what Google Docs uses. It requires a central server to dictate order.
  • Conflict-Free Replicated Data Types (CRDTs): Data structures designed so that operations can be applied in any order and always converge. Clients can merge changes peer-to-peer. This is what Figma and modern editors often use. It trades server complexity for larger memory footprints and complex data structures.

Session Routing

Because OT requires a single source of truth, all users editing Document X must connect to the same server node. The API Gateway queries a Redis Session Registry to find which node 'owns' Document X. If none exists, it assigns one. If that node crashes, clients reconnect, the gateway assigns a new node, and the new node reconstructs the document state from the database.

Event Sourcing & Snapshots

The database stores the document as an event stream (every keystroke is an event). To prevent loading 100,000 events when opening a document, the server periodically compacts the events into a Snapshot (e.g., every 1,000 operations or every 5 minutes). When opening a document, the server loads the latest Snapshot and applies only the events that occurred after it.

Bottlenecks & Solutions

The single Session Server per document becomes a bottleneck if a document has thousands of concurrent viewers (e.g., a public announcement doc). To solve this, the architecture splits into Editors (routed to the main Session Server) and Viewers (routed to read-only replicas that receive broadcasted state updates via a pub/sub system like Redis PubSub).

Interview Follow-up Questions

Q: How do you handle a user making changes while offline on a train?

The client stores operations in a local queue and applies them to the local UI instantly (optimistic UI). When the connection is restored, the client flushes its queue to the server. The server's OT algorithm or CRDT will merge those operations with whatever happened in the meantime, and send back the reconciled state.

Q: What happens if the Session Server handling a document crashes?

Clients detect the dropped WebSocket and attempt to reconnect. The load balancer assigns them to a new node. The new node detects it doesn't have the document state in memory, fetches the latest Snapshot from the database, replays recent operations from the event log, and then resumes handling traffic. There is a brief pause, but no data is lost.