Skip to main content
GUN uses a state-based CRDT (Conflict-free Replicated Data Type) approach to ensure eventual consistency across all peers, even in the presence of network partitions, concurrent updates, and offline operations.

State-Based CRDT

GUN’s conflict resolution is built on the concept of state timestamps - each property update includes a monotonically increasing timestamp that determines which value wins.

How It Works

Every update in GUN includes metadata:
Source: ~/workspace/source/src/state.js:18-27

State Vector Clocks

State Generation

GUN generates unique, monotonically increasing timestamps:
Source: ~/workspace/source/src/state.js:4-10

Components

  • Base timestamp: Milliseconds since epoch
  • Sub-millisecond counter: Allows multiple updates within the same millisecond
  • Drift compensation: Accounts for clock skew across machines
Source: ~/workspace/source/src/state.js:12

Getting State Values

Source: ~/workspace/source/src/state.js:13-17

Setting State Values

Source: ~/workspace/source/src/state.js:18-27

Last-Write-Wins (LWW)

GUN uses a Last-Write-Wins strategy at the property level, not the document level.

Property-Level Resolution

Why Property-Level?

This approach provides better merge semantics:

Handling Conflicts

Automatic Merging

GUN automatically merges concurrent updates:

Conflict Detection

You can detect conflicts by tracking state changes:

Dealing with Clock Skew

Drift Compensation

GUN includes a drift parameter to handle clock differences:
Source: ~/workspace/source/src/state.js:11

Best Practices

  1. Use NTP: Keep system clocks synchronized
  2. Trust timestamps: Don’t try to “fix” timestamps
  3. Monotonic clocks: GUN ensures timestamps always increase locally

Advanced Conflict Strategies

Counter CRDTs

For counters, use increment operations:

Set CRDTs

GUN’s .set() implements a grow-only set:

Custom Resolution

Implement custom conflict resolution by tracking versions:

Vector Clocks vs State Timestamps

GUN uses state timestamps rather than traditional vector clocks:

Vector Clocks

State Timestamps (GUN)

Advantages:
  • Simpler to implement and reason about
  • Constant space per property (not per peer)
  • Works well for eventually consistent systems
  • Natural ordering with timestamps
Tradeoffs:
  • Requires reasonably synchronized clocks
  • Cannot detect all concurrent updates (some are arbitrarily resolved)
  • May lose updates if clocks are severely misaligned

Data Integrity

Hash-Based Deduplication

GUN uses content hashing to detect duplicate messages:
Source: ~/workspace/source/src/mesh.js:73

Preventing Loops

The mesh layer prevents infinite message loops:
Source: ~/workspace/source/src/mesh.js:76

Convergence Guarantees

Eventual Consistency

GUN guarantees that all peers will eventually converge to the same state:
  1. All updates are commutative: Order doesn’t matter
  2. All updates are idempotent: Applying twice has same effect
  3. All peers use the same merge rules: Deterministic conflict resolution

Convergence Time

The time to convergence depends on:
  • Network latency between peers
  • Number of hops in the mesh network
  • Message batching intervals
  • Peer availability

Testing Conflicts

Simulating Offline Scenarios

Concurrent Writes

Best Practices

  1. Embrace eventual consistency: Don’t rely on immediate consensus
  2. Use property-level updates: More granular merging
  3. Avoid read-modify-write: Use semantic operations instead
  4. Implement tombstones: Mark deletions rather than removing data
  5. Monitor state timestamps: Debug sync issues
  6. Trust the CRDT: Don’t try to “fix” conflicts manually
  7. Design for commutativity: Order-independent operations
  8. Test offline scenarios: Ensure your app handles partitions gracefully

Common Patterns

Optimistic UI Updates

Collaborative Editing

Debugging

Inspecting State Metadata

Monitoring Conflicts

Next Steps