---
topic: system-design
author: Crashtech Editorial
date: Aug 19, 2026 · read: 8 min
---

CRDTs: Conflict-Free Collaboration at 60fps

Every user edits a local replica; operations merge automatically into an identical state regardless of arrival order, with no central locking.

Five designers working on the same Figma file. One changes a button color. Another rearranges a grid. A third deletes a frame—while offline. The changes arrive at the server in a different order than they were made. Thirty milliseconds later, all five screens show the identical state. No locks. No “save conflict” dialogs. No refresh required. This is real-time collaboration at the edge of what feels magic—and it rests entirely on a mathematical property: operations that commute.

Centralized locking vs local CRDT replicas Left: centralized locking freezes state for all users until one edit saves. Right: CRDTs let all four users edit local replicas simultaneously; operations merge automatically into an identical state.

The Locking Trap

The naive approach to real-time collaboration is deceptively simple: one server, one source of truth. When Alice starts editing a layer, the server locks it. Bob tries to edit the same layer and gets a spinner or a “locked by Alice” message. He waits. Alice saves; the lock releases; Bob can finally edit. This is how spreadsheets worked for decades.

The problem is latency. On a 50 ms round trip (common for intercontinental teams), Alice typing a keystroke means:

  1. Send keystroke to server (~25 ms)
  2. Server acquires lock, broadcasts to Bob (~25 ms)
  3. Bob’s screen updates

That’s 50 ms minimum for each keystroke. Scale to five concurrent editors and the server becomes a bottleneck. Add offline support—a designer on a plane editing without connectivity—and the model breaks entirely. You can’t acquire a lock from a server you can’t reach.

The CRDT Breakthrough

The insight: what if we don’t lock at all? What if Alice edits a local copy, Bob edits a local copy, and both send their operations to a server that just stores them? Then, when Charlie opens the file, the server replays all operations—Alice’s, Bob’s, in any order—and Charlie’s state converges to what Alice and Bob both see, automatically, with no conflicts.

This works if operations are commutative: the result of A → B is identical to B → A. A simple example:

Alice: Insert "red" at position [3]
Bob:   Insert "blue" at position [5]

If Alice edits first, then Bob: "...redblue"
If Bob edits first, then Alice: "...redblue" (position [5] shifts)

For this to be true, insert operations must be tagged with unique site identifiers. Instead of inserting at position 3, Alice says: “insert ‘red’ after my previous operation [Alice-op-7].” Bob says: “insert ‘blue’ after my previous operation [Bob-op-5].” Now the order doesn’t matter—each operation is anchored to a causally previous op, and replaying them in any order reconstructs the identical document.

This is the core of a CRDT: a data type where operations are designed to commute, so any replica applying the same set of operations—in any order—arrives at the same state.

The Mechanism: Concurrent Edits Merge Deterministically

Let’s trace how Figma handles three concurrent edits:

CRDT merge mechanism showing three replicas receiving operations in different orders Three replicas each receive the same three operations in a different order (A→B→C, C→A→B, B→C→A), but apply them deterministically and converge to an identical state.

Step 1: Initial state.
All three users start with [user, name, text].

Step 2: Concurrent operations.

  • Alice inserts “admin” at the start
  • Bob deletes “text” at the end
  • Charlie inserts “email” at position 3

Each operation is timestamped and tagged with the user’s unique ID: Op₁ [Alice, timestamp-1], Op₂ [Bob, timestamp-2], Op₃ [Charlie, timestamp-3].

Step 3: Message arrival in different orders.

  • Alice’s replica receives: Op₁, Op₂, Op₃ (Alice’s ops first)
  • Bob’s replica receives: Op₃, Op₁, Op₂ (Charlie’s ops first)
  • Charlie’s replica receives: Op₂, Op₃, Op₁ (Bob’s ops first)

Step 4: Deterministic merge. The CRDT algorithm assigns a total order to all operations based on their metadata. For example, operations are ordered by (timestamp, site_id) pairs. Even though the replicas receive messages out of order, they each apply the same total order:

  1. Op₁ [Alice, ts=100]
  2. Op₂ [Bob, ts=101]
  3. Op₃ [Charlie, ts=102]

All three replicas converge: [admin, user, email].

Why Position Matters More Than Index

Traditional text editors track positions by absolute index:
Insert "x" at index 3Insert "y" at index 5

But if the first operation also added text, index 5 might now point to the wrong place. This breaks commutativity.

CRDTs solve this by using relative positioning. Instead of “insert at index 3,” you say “insert after the character with ID char-7.” The character ID is immutable and independent of position. When operations are applied in any order, each insert finds its anchor (the previous character) and places the new character after it. Commutativity is restored.

Figma uses a similar strategy with fractional indices. Each layer has a unique ID that acts as its position. Concurrent moves and reorders don’t conflict because they’re anchored to these immutable IDs, not to volatile indices.

Commutativity is the whole game

A CRDT is only as good as the commutativity of its operations. If your operation is “set field X to value Y” without causal context, you have a problem: two users setting X to different values concurrently will produce different results depending on order, violating the CRDT promise. The fix is to bake causality into the operation: “set field X to Y because the user chose Y at [time-T-with-ID-Q].”

The Trade-off: Memory, Bandwidth, and Complexity

Memory cost.
Each user’s browser keeps a full replica of the document. For Figma (millions of designs at 1–5 MB each), this is acceptable. For a 100 GB spreadsheet, it’s not. CRDTs are best for documents small enough to fit in browser memory.

Bandwidth cost.
The network burden is low per user: Figma sends only the operations (a few bytes per keystroke), not the full state. But under heavy concurrent editing, the operation log grows. A 10-minute brainstorming session with 5 users making 100 edits/second = 300,000 operations. Stored naively, that’s significant. In practice, Figma periodically snapshots the state and discards old operations, bounding the log.

Undo/redo complexity.
In a centralized system, undo is trivial: reverse the last server operation. In a CRDT, Alice undoes her op-7 while Bob’s op-8 is already queued. The undo operation itself must be commutative with future ops. Figma solves this by tagging undos with causality metadata and ensuring they apply in the correct logical order, not just wall-clock order.

Offline support.
The real win. Alice edits offline for 10 minutes, accumulating local operations. She reconnects; the client sends all operations to the server. The server merges them with ops from Bob and Charlie, and Alice’s changes integrate seamlessly, without conflicts. Try that with pessimistic locking.

When NOT to Use CRDTs

Single-writer workflows.
If only one person edits the document at a time, the overhead of maintaining replicas and merging operations is pure waste. A simple client-server model with optimistic locking is cheaper.

Non-commutative operations.
Some operations just don’t commute nicely. “Transfer $100 from account A to account B” is not commutative with “apply a 5% fee”—the fee amount depends on which happened first. CRDTs force you to redesign the operation (perhaps: “transfer $100, then recalculate fees based on current balance”). This is solvable but adds friction.

Low-latency critical paths.
Replicas add eventual-consistency semantics. If you need to guarantee that operation X happens before operation Y globally, CRDTs give you causal consistency but not linearizability. Financial systems often need the latter.

Good fit for CRDT green
  • Rich documents (design files, collaborative notes)
  • Offline-first use cases
  • High concurrency (5+ simultaneous editors)
  • Distributed teams with high latency
Poor fit for CRDT amber
  • Single-writer, low-concurrency workflows
  • Operations with non-commutative semantics
  • Small-scale systems where consistency is critical
  • Memory-constrained embedded systems

The Figma Implementation

Figma’s real-time multiplayer engine (shipped 2019) uses a CRDT similar to the academic Yjs data structure. Every object (frame, shape, text) gets a unique ID. Edits are operations: insert, delete, move, set_property. Each operation carries:

  • Unique operation ID (prevents duplicates if retransmitted)
  • Causality metadata (which operation preceded this one)
  • Site ID (which user made this edit)
  • Timestamp (for tie-breaking in operation ordering)

When a new user joins or reconnects, Figma sends them:

  1. A snapshot of current state (latest document + a timestamp)
  2. All operations after that timestamp (so they can fast-forward)

This bounds the amount of state a newcomer must ingest while preserving consistency.

The result: Figma’s 60 fps responsiveness. Alice types; her local replica updates instantly (0 ms latency from her perspective). The operation propagates to the server in the background (~50 ms). Bob’s replica merges it within another 50 ms. To Bob, the edit appears seamlessly. No locks, no spinners, no conflicts. All coordinated through the mathematical guarantee that operations commute.

Conclusion

CRDTs solved a hard problem: how to build a collaborative tool where five people can edit at once, offline, with 50+ ms latency between continents, and the application never shows a conflict or asks for a manual merge. The trick is not to avoid conflicts but to design operations so conflicts don’t exist—to choose a data model where the order doesn’t matter.

This shifted the burden from the server (which had to resolve conflicts) to the client library (which had to ensure commutativity). For Figma, Google Docs, and increasingly for any realtime-collaborative system, it’s been the breakthrough that made the experience feel effortless.

Advertisement
Advertisement

Frequently asked questions

What is a CRDT and why does it matter for real-time collaboration?

A CRDT (Conflict-free Replicated Data Type) is a data structure where concurrent edits by multiple users automatically merge into an identical result, regardless of the order messages arrive. This eliminates the need for central locking and enables true offline-first, lockless collaboration at millisecond latency.

How do CRDTs handle concurrent edits without a central server referee?

CRDTs use mathematically designed operations where the order of execution doesn't matter—they're commutative. Each operation is tagged with metadata (unique IDs, timestamps, site IDs) so every replica can apply the same operations in a consistent order and converge to the same final state.

Why did Figma move from operational transforms to CRDTs?

Operational transforms were complex to implement correctly and required a central server to resolve conflicts in real time. CRDTs are mathematically simpler: each replica independently applies the same operations deterministically, so Figma could handle offline edits, peer-to-peer sync, and better support for undo/redo.

What's the memory and bandwidth cost of running replicas locally?

Each user's browser keeps a full copy of the document state (replicas) plus an operation log of all edits. For Figma's typical designs (1–5 MB), this is acceptable. The network cost is low because only operations (not full state) are transmitted. Under heavy concurrent editing, bandwidth is proportional to op count, not document size.

When is CRDT-based collaboration the wrong choice?

CRDTs add complexity and memory overhead. For purely server-side, single-writer workflows (a spreadsheet with one editor at a time), the cost isn't justified. Also, CRDTs struggle with operations that aren't naturally commutative—like 'set this field to X' without context—requiring careful operation design.

Sources & further reading

/* Comments */