QUICK START:HTMLCSSJavaScriptTypeScriptPythonSQLReactNext.jsNode.jsLinux & UbuntuKotlinSwiftC# / .NETJavaGoRustC++DSASystem DesignDevOpsCybersecurityAI / ML
Advanced 28 min readModule: Module 13: Conflict-Free Replicated Data Types (CRDTs)

CRDTs & Real-Time Collaborative Architecture

Build real-time multi-user collaborative systems (like Figma, Google Docs, Notion): Operation-based vs State-based Conflict-Free Replicated Data Types (CRDTs), PN-Counters, Last-Write-Wins Element Sets (LWW-Set), fractional indexing, and Local-First architecture.

What You Will Learn in This Lesson

  • Why Operational Transformation (OT) requires a centralized server and how CRDTs enable peer-to-peer collaboration
  • The mathematical properties of CRDTs: Commutativity (A + B = B + A), Associativity, and Idempotence (A + A = A)
  • State-based CvRDTs (Lattice Join semi-lattices) vs Operation-based CmRDTs
  • Designing a Conflict-Free Last-Write-Wins (LWW) Register with hybrid timestamps

Introduction & Core Concept

In traditional web architectures, all client mutations must pass through a single central database lock to resolve conflicts. In Local-First and real-time collaborative applications (Figma, Notion, Linear), users must be able to edit data offline on airplanes and merge changes seamlessly when reconnecting. Conflict-Free Replicated Data Types (CRDTs) are mathematically proven data structures that can be updated concurrently on multiple devices without coordination and guarantee eventual convergence to identical state.
WHY DOES THIS MATTER IN THE REAL WORLD?

CRDTs allow applications to work 100% offline with zero latency, syncing peer-to-peer or via WebSockets with zero conflict resolution popups or data loss.

Syntax & Structure

javascript
// CRDT Join Semi-Lattice
merge(stateA, stateB) = max(stateA.timestamp, stateB.timestamp)

Implementing a Conflict-Free Replicated LWW-Element-Set in JavaScript

javascript
javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
// Conflict-Free Replicated Data Type (CRDT): LWW-Element-Set
class LWWElementSet {
constructor() {
// Maps element -> latest add timestamp
this.addSet = new Map();
// Maps element -> latest remove timestamp
this.removeSet = new Map();
}
add(element, timestamp = Date.now()) {
const existing = this.addSet.get(element) || 0;
if (timestamp > existing) {
this.addSet.set(element, timestamp);
}
}
remove(element, timestamp = Date.now()) {
const existing = this.removeSet.get(element) || 0;
if (timestamp > existing) {
this.removeSet.set(element, timestamp);
}
}
has(element) {
const addTime = this.addSet.get(element);
if (!addTime) return false; // Never added
const removeTime = this.removeSet.get(element) || 0;
// Bias towards Add if timestamps are equal
return addTime >= removeTime;
}
// Mathematical Semi-Lattice Merge (Commutative, Associative, Idempotent)
merge(peerCRDT) {
const merged = new LWWElementSet();
// Merge Add Sets (Take maximum timestamp per element)
const allAddKeys = new Set([...this.addSet.keys(), ...peerCRDT.addSet.keys()]);
for (const key of allAddKeys) {
const t1 = this.addSet.get(key) || 0;
const t2 = peerCRDT.addSet.get(key) || 0;
merged.addSet.set(key, Math.max(t1, t2));
}
// Merge Remove Sets
const allRemoveKeys = new Set([...this.removeSet.keys(), ...peerCRDT.removeSet.keys()]);
for (const key of allRemoveKeys) {
const t1 = this.removeSet.get(key) || 0;
const t2 = peerCRDT.removeSet.get(key) || 0;
merged.removeSet.set(key, Math.max(t1, t2));
}
return merged;
}
}
// Client 1 (Offline in Tokyo) & Client 2 (Offline in London)
const clientTokyo = new LWWElementSet();
const clientLondon = new LWWElementSet();
clientTokyo.add("Document_Design_Doc", 100);
clientLondon.add("Document_Design_Doc", 100);
clientLondon.remove("Document_Design_Doc", 150); // London deletes later
// Merge both sets across network
const reconciledState = clientTokyo.merge(clientLondon);
console.log("=== CRDT LWW-Element-Set Convergence Engine ===");
console.log("Document exists after concurrent merge:", reconciledState.has("Document_Design_Doc")); // False (London delete won)
console.log("✅ Replicas converged to identical state with zero central server coordination!");

Line-by-Line Technical Breakdown

1Text Editing CRDTs (Yjs & Automerge): Plain sets cannot model rich text because characters have positions. Text CRDTs use Fractional Indexing and unique item IDs (Client ID + Sequence Number) to insert characters between existing characters without shifting array indices.

Try It Yourself (Interactive Editor)

Modify the code in real-time and click Run to test live browser output and console logs.

Intelligent Code Runner & Live Sandbox[JAVASCRIPT]
JAVASCRIPT SOURCE EDITOR
Interactive Live Code

Common Mistakes & How to Avoid Them

#1: Using wall-clock `Date.now()` across devices without clock synchronization, allowing client clock drift to overwrite valid updates.

Device system clocks drift by hundreds of milliseconds. Hybrid Logical Clocks (HLC) combine physical time with logical counters to prevent clock skew overwrites.

Incorrect / Antipattern
timestamp = new Date().getTime() // Fragile due to NTP clock skew
Correct / Professional Solution
timestamp = hybridLogicalClock.now() // Use Hybrid Logical Clocks (HLC)

Industry Best Practices & Professional Standards

  • Use production CRDT libraries (Yjs, Automerge, ElectricSQL) for text editing and real-time collaboration.
  • Use Hybrid Logical Clocks (HLC) to maintain causal ordering across disconnected clients.
  • Store CRDT state snapshots periodically to prevent tombstones from bloating memory.

Lesson Summary & Core Takeaways

  • CRDTs enable offline, peer-to-peer real-time collaborative applications.
  • Mathematical commutativity and idempotence guarantee deterministic conflict resolution.
  • Powers modern local-first collaborative platforms like Figma, Notion, and Linear.