# CRDT vs Operational Transform: Conflict Resolution for Real-Time Collaborative Editors

> Deep-dive into CRDT vs Operational Transform for real-time collaborative editing—architecture tradeoffs, convergence guarantees, and when to use each approach.

- **Published:** 2025-04-07
- **Author:** Clixo
- **Reading time:** 6 min read
- **Tags:** crdt, operational-transform, real-time, collaborative-editing, websockets
- **Canonical URL:** https://clixo.sh/blog/crdt-vs-operational-transform-real-time-editing

Two users edit the same document simultaneously. Without a conflict resolution mechanism, one user's changes will silently overwrite the other's. The two dominant approaches to this problem — Operational Transform and CRDTs — both solve it, but they make different architectural tradeoffs that affect everything from your server topology to your offline support story.

## The Core Problem: Concurrent Edits

Consider a document containing the text `"hello"`. User A deletes the `"h"` at position 0. Simultaneously, User B inserts `"!"` at position 5. If both operations reach the server in A-then-B order, the document becomes `"ello!"` as expected. But if the operations are applied naively without transformation, B's insert at position 5 hits an index that shifted when A's delete was applied, producing `"ello!"` on one client and `"ello! "` on another. The clients diverge.

Both OT and CRDTs prevent divergence. They differ in how.

## Operational Transform (OT)

OT was formalized in the late 1980s and is the approach behind Google Docs and early collaborative editors.

### How It Works

When two operations are concurrent — meaning neither happened-before the other in the causal sense — OT transforms one operation against the other before applying it. The transformation adjusts positional indices so that the intent of both operations is preserved even when applied in different orders.

For the example above: B's insert at position 5 is transformed to position 4 after accounting for A's delete, producing `"ello!"` on all clients regardless of the order operations arrive.

### The Server Requirement

```mermaid
sequenceDiagram
  participant A as "Client A"
  participant S as "Server"
  participant B as "Client B"
  A->>S: op1 (delete position 0)
  B->>S: op2 (insert position 5)
  S->>S: serialize ops in canonical order
  S->>S: transform op2 against op1
  S->>A: broadcast transformed op2
  S->>B: broadcast op1
  note over A,B: Both clients converge to same state
```

Classical OT requires a central server to serialize concurrent operations. Clients send their operations to the server, which applies them in a canonical order and transforms them before broadcasting to other clients. Without a central arbiter, ensuring convergence across all clients becomes provably difficult — a known limitation called the "dOPT puzzle."

This makes OT a natural fit for server-centric architectures, but it complicates peer-to-peer and offline-first scenarios.

### Implementation Complexity

Correct OT implementation is hard. The transformation functions must satisfy two formal properties — TP1 and TP2 — and proving correctness requires careful mathematical verification. Most teams reach for a battle-tested library rather than implementing OT from scratch. The original ShareDB (used in CodeMirror's server-side OT) is the most widely deployed option for document editing over WebSockets.

## CRDTs: Conflict-Free Replicated Data Types

CRDTs are a class of data structures designed so that concurrent updates always converge to the same state, regardless of the order in which they are applied — without any central coordination.

### How CRDTs Achieve Convergence

CRDTs achieve convergence through algebraic properties: operations are commutative (order doesn't matter), associative (grouping doesn't matter), and idempotent (applying an operation twice is the same as applying it once). These properties mean any two replicas that have seen the same set of operations will always arrive at the same state.

For text, CRDT implementations like Yjs and Automerge assign each character a globally unique identifier rather than a mutable position index. A delete marks the character as deleted by ID rather than by position. Insertions are anchored relative to neighboring characters by their stable IDs. Positions shift, but IDs are permanent — so operations never interfere.

### No Central Server Required

Because CRDTs converge without coordination, they work in peer-to-peer topologies. Replicas can diverge while offline and merge cleanly when they reconnect, with no server arbitrating the order. This makes CRDTs the right choice for offline-first products and local-first architectures.

### Libraries Worth Knowing

- **Yjs** — the most production-mature JavaScript CRDT library; used in Tiptap, Remirror, and a range of collaborative editors. Integrates directly with WebSocket providers.
- **Automerge** — a JSON CRDT library with a JSON-patch-style API; better suited to structured data than rich text
- **Loro** — a newer Rust-based CRDT library with a WebAssembly build, designed for performance at scale

## CRDT vs Operational Transform: Direct Comparison

| Property | Operational Transform | CRDT |
|---|---|---|
| Central server required | Yes (for convergence) | No |
| Offline-first support | Limited | Strong |
| Memory overhead per character | Low | Higher (stores metadata per element) |
| Proven production deployments | Google Docs, ShareDB | Figma, Notion, Linear |
| Implementation complexity | Very high | Moderate (with a library) |
| Performance at large documents | Good | Can degrade; depends on implementation |

## When to Choose OT

- You already have a server-centric WebSocket architecture and a single source of truth
- Rich text or code editing where character-level transforms are well-understood
- You are using ShareDB or a similar mature OT framework and do not need offline-first capability

## When to Choose CRDTs

- The product needs offline editing with conflict-free sync when users reconnect
- Peer-to-peer collaboration where a central server is not always available
- You are building on Yjs, which has mature WebSocket providers and editor integrations out of the box
- Structured data (JSON, trees, maps) where CRDT semantics map naturally

## The Practical Advice

For most new collaborative products built on Node.js with WebSockets today, **Yjs is the pragmatic starting point**. It abstracts the CRDT complexity, ships with WebSocket and WebRTC providers, and integrates with ProseMirror, CodeMirror, and Quill. You can implement a collaborative text editor in days rather than weeks.

OT remains appropriate if you are extending an existing system that already has a central conflict-resolution server and the team is deeply familiar with the transform functions.

Neither approach eliminates the need for careful WebSocket infrastructure. You still need to handle reconnection, message ordering across the transport layer, and awareness (presence, cursor tracking) as a separate concern from the document CRDT.

If you are building a collaborative product and want to get the data model and real-time architecture right before you write the first line, [start a conversation with Clixo](https://clixo.sh/#contact). We design and build the full stack from the conflict-resolution layer through the UI.

---

Clixo · 1141 W Bryn Mawr Ave, Itasca, IL 60143, US · [hello@clixo.sh](mailto:hello@clixo.sh)
[Start a build](https://clixo.sh/#contact) · [All services](https://clixo.sh/services) · [Agent guide (llms.txt)](https://clixo.sh/llms.txt)
