cswork / libraryOpen practice workspace

Articles

Real-Time Collaborative Editor System Design: OT, CRDTs, and Conflict Resolution

A collaborative editor must do more than distribute keystrokes. Two people can edit the same position, disconnect, reconnect, undo their work, and lose permission while their clients still have queued changes. A strong system design answer separates text convergence from durable acceptance, authorization, and user intent. OT and CRDTs address part of that problem; neither replaces the rest of the service.

Named library behavior is supported by official documentation; the traces and proposed service contracts here are original teaching examples, not candidate reports.

Establish the document and operation model

Choose a plain-text document before discussing rich text, tables, or embedded objects. Declare whether operation positions count Unicode code points, UTF-16 units, or another editor-defined unit. Two replicas cannot correctly transform offsets if they count the same string differently.

For an original baseline, users see local edits immediately, accepted edits survive a server restart, and authorized replicas converge after receiving the same accepted changes. Offline editing is allowed, but synchronization may reject changes if permissions were revoked. Presence and cursors are temporary hints, not durable document content.

Separate an operation being visible locally from being accepted durably. A client can display a pending edit without asserting that the shared service has committed it. Show that distinction in the interface, especially when the network disappears or the server refuses a change.

Start with document-level access control and bounded document size. Global search, cross-document transactions, and media storage are follow-ups. This keeps the initial synchronization problem small enough to explain instead of hiding it inside a large architecture diagram.

Explain operational transformation using a concrete offset

Operational transformation, or OT, changes an operation so it remains meaningful after another operation has modified its original context. In a text editor, a preceding insertion can shift the position of a later insertion. The transformation must use a declared operation model and preserve the intended ordering rules.

Take the original base text “ab.” Alice inserts X at position 1; Bob independently inserts Y at position 1. Suppose this teaching protocol orders Alice's operation first and resolves equal-position insertions in that order. Applying Alice gives “aXb”; Bob's transformed insertion moves to position 2, giving “aXYb.”

Bob initially sees “aYb.” His client must reconcile its pending operation with Alice's accepted operation according to the same protocol. It cannot simply apply Alice at the raw original offset while assuming every replica will somehow converge. Changing the tie-break rule is possible, but all participants must agree on it.

Official ShareDB documentation describes a backend built on OT with real-time synchronization and offline reconnection. That is evidence of a supported mechanism, not proof that a two-line offset rule is a complete OT implementation. Inserts, deletes, overlapping ranges, pending buffers, and multiple concurrent operations require the full transformation protocol.

Contrast CRDT identity with mutable positions

A conflict-free replicated data type, or CRDT, represents shared state with merge rules designed for convergence under specified assumptions. Sequence CRDTs commonly identify elements independently of their current visible numeric offsets. The particular ordering, deletion, and synchronization rules depend on the implementation.

For a conceptual alternative to the OT trace, Alice and Bob attach their inserts to the same existing context and use distinct operation identities. A deterministic tie-break orders the concurrent inserts. Both replicas reach the same sequence after integrating both accepted operations, even if arrival order differs.

Do not claim every CRDT must produce “aXYb.” Our example declares that order to make the exercise inspectable; a different implementation can choose another consistent order. Convergence means agreement under the algorithm, not that users necessarily prefer the resulting sentence.

Official Yjs document update documentation states that its updates are commutative, associative, and idempotent. Updates can be delivered in different orders and repeated while replicas synchronize after receiving the complete update set. These properties do not make unauthorized updates acceptable or establish that an update has been durably stored.

Choose from requirements rather than slogans

An OT service with a central accepted revision sequence can fit a connected editing product with a mature transformation library. A CRDT library can fit offline merging and flexible replication. Both may use central servers for persistence, authentication, room membership, and distribution.

Avoid saying “OT requires perfect connectivity” or “CRDT means no servers.” ShareDB explicitly supports reconnection, and a Yjs deployment still needs providers and storage decisions. Compare the implementations you intend to use, their supported data types, history behavior, and operational costs.

For our baseline, choose an established synchronization library rather than inventing one during the interview. Explain how the server authenticates each document session, persists accepted updates, and broadcasts them. Separate the library's merge contract from your service's storage and access contract.

Rich text adds constraints that a plain sequence does not settle: formatting ranges, nested objects, schema validity, and edits to deleted structures. A convergent representation can still produce content that violates application rules. State whether invalid structures are rejected, normalized, or represented as visible errors.

Make reconnect a synchronization protocol

Maintain an accepted update log or equivalent durable state and a versioned snapshot. A reconnecting client supplies its synchronization state; the server returns the missing accepted information. The client uploads its pending local work only through the current authorization path.

Yjs exposes state vectors and update-difference APIs for synchronization. Its alternative update API can merge updates without loading a full document, but the official documentation notes that this alone does not garbage-collect deleted content. Do not present merging binary blobs as an automatic solution to unbounded history.

An original crash trace has accepted updates U1 through U40 in a durable log and a snapshot covering U1 through U30. Recovery loads the snapshot, replays U31 through U40, and verifies the resulting document. A snapshot claiming U40 while containing only U30 would incorrectly cause recovery to skip accepted work.

Publish snapshots with their covered boundary atomically, or use a manifest that selects a completed snapshot. Trim the covered log only after the snapshot is safely stored and recoverable. If a client reconnects from a state older than retained history, define a full synchronization or rebase path rather than pretending its old revision is still supported.

Handle permission revocation before accepting updates

A WebSocket authorized at connection time may remain open after membership changes. Recheck authorization at the acceptance boundary, revoke subscriptions when permissions change, and ensure fan-out does not keep sending new content to a removed user. Room IDs alone are not authorization.

Suppose Bob edits offline at document state D30, loses write access, and reconnects after the server reaches D40. His client may have a perfectly mergeable update. The server must still reject its application to the shared document under the declared policy. Mergeability cannot override the access decision.

Separate rejecting an update from destroying the user's local work. A proposed product behavior preserves Bob's pending text locally and explains that it cannot synchronize. Whether export remains permitted depends on the product's policy; it should not be decided by the merge algorithm.

Revocation cannot erase content already delivered to a client. State that boundary when discussing confidentiality. Server authorization protects future acceptance and distribution; it cannot guarantee remote deletion of an offline copy that another party already possesses.

Treat cursors and undo as separate semantics

A cursor stored as offset 5 can jump to the wrong text when someone inserts earlier in the document. The official Yjs relative-position API describes positions associated with the shared structure, which can be resolved into current absolute positions. A deleted referenced type can make resolution fail, so the interface needs a fallback.

Presence should not inflate the permanent update log. Yjs awareness documentation treats awareness as a separate protocol for information such as online users and cursor locations. Rate-limit it, expire stale participants, and distinguish disconnected presence from document deletion.

Undo is also not a blanket rollback to an old snapshot. If Alice undoes her insertion after Bob contributes another character, replacing the entire document would erase Bob's accepted work. Define local undo scope, transaction grouping, and how concurrent edits affect inverse operations.

For the “aXYb” exercise, undoing Alice's X should preserve Bob's Y under our proposed local-edit undo semantics. A full implementation must identify Alice's contribution and use its library's supported undo behavior. The short trace specifies the expected result; it is not a universal inverse-operation recipe.

Scale by active documents and bounded work

Route connected sessions by document ID so a document's active participants meet at a responsible service or room. Replicate durable state separately from transient connections. A leader change needs ownership fencing where two servers could otherwise both claim the same acceptance authority.

One celebrity document can become hot even when the rest of the fleet is idle. Partitioning by document cannot divide that document's coordination cost automatically. Bound participant count, update size, fan-out queues, and history synchronization work; coalesce presence updates rather than durable edits unless the algorithm explicitly supports it.

Slow clients should receive bounded queues and a resynchronization path. Disconnecting a client whose queue exceeds limits can be safer than exhausting the room server. Explain how it obtains a current state without losing its acknowledged changes or accidentally resubmitting them as new edits.

Observe convergence failures, pending-edit age, reconnect duration, snapshot lag, authorization rejection, and per-document tail latency. A low average message delay does not prove that an offline client reconciles correctly after a restart.

Practise invariants with adversarial histories

Practice questionWhat to practise
Design a Real-Time Collaborative Document Editor with Concurrent EditsTrace concurrent edits and reconnect.
Design a Collaborative EditorExplain the chosen operation model.
Text Editor in Four Stages: Buffer, Undo/Redo, Trie Autocomplete, Collaborative OTKeep undo and buffer rules apart from sync.
Design collaborative document editing backendDefine durable acceptance and document routing.
Compress editor keystrokes into insert/delete/skipDistinguish positional encoding from concurrent merge.

Run histories containing reordered delivery, duplicate updates, concurrent inserts and deletes, local undo, permission revocation, and restart between persistence and acknowledgment. Compare all authorized replicas after complete delivery, then check that acknowledged changes survived recovery.

Convergence alone is insufficient evidence: two replicas can agree on the same incorrectly authorized document. Assert permission and durability invariants separately. For snapshots, compare replay from the beginning with snapshot-plus-tail recovery at several boundaries.

Return to the concurrent document editor exercise and explain one accepted edit, one offline pending edit, and one rejected edit from client display through recovery. That trace makes your OT or CRDT choice reviewable and gives each service component a concrete responsibility.

Sources and Further Reading

Primary references checked September 30, 2026. Library convergence properties must be combined with application-specific authorization, persistence, and editor semantics.