Skip to content
LowLevelDesign Mastery

Conflict Resolution Strategies

When multiple updates collide, how do you decide?

In distributed systems, conflicts happen when multiple nodes update the same data simultaneously without coordination.

Write conflict: User A changes Hello to Hi while User B changes Hello to Hey at the same time, leaving the system to pick a winner

Last-Write-Wins (LWW) is the simplest conflict resolution strategy: the most recent write (by timestamp) wins.

Last-write-wins resolution: Node 2's write of x = 200 at 10:00:05 beats Node 1's x = 100 at 10:00:00, which is lost

Key Characteristic: Uses timestamps to determine the winner. The write with the latest timestamp wins.

Last-write-wins in document editing: concurrent edits Hi and Hey are compared by timestamp and User B's later Hey wins Three problems with last-write-wins: lost data on simultaneous writes, wrong winners from clock skew, and no causal ordering
ProblemDescriptionExample
Data LossSimultaneous writes lose oneUser A’s edit is lost
Clock SkewWrong timestamp winsSlow clock makes old write win
No Causal OrderIgnores dependenciesReply might appear before original message

Vector clocks track causal relationships between events. They help detect conflicts and preserve logical ordering.

A vector clock is a vector of logical timestamps, one per node. Each node increments its own timestamp when it performs an operation.

Vector clocks on three nodes, each incrementing its own component, with rules for happened-before versus concurrent vectors Vector clock chat example: Hello [1,0,0] precedes Hi [1,1,0] and Hey [1,0,1], which are concurrent and flagged as a conflict

Key Insight: Vector clocks detect concurrent events (conflicts) vs causally related events (ordered).

Three vector clock comparison rules: happened before means ordered, neither less or equal means concurrent conflict, equal means same event

Comparison Algorithm:

  • V1 < V2 if all components of V1 ≤ V2 and at least one is less than
  • V1 || V2 (concurrent) if neither V1 < V2 nor V2 < V1
  • V1 == V2 if all components are equal

Strategy 3: CRDTs (Conflict-free Replicated Data Types)

Section titled “Strategy 3: CRDTs (Conflict-free Replicated Data Types)”

CRDTs (Conflict-free Replicated Data Types) are data structures designed to never conflict. They use mathematical properties to ensure all replicas converge to the same state.

CRDT principle: instead of complex conflict resolution logic, mathematical properties make replicas converge automatically

Key Property: CRDTs use commutative and associative operations, so order doesn’t matter. All replicas converge to the same state automatically.


Operation-based CRDTs replicate operations (e.g., “increment counter”, “add element to set”).

Operation-based CRDT counter: two nodes each replicate an increment operation, and applying both in any order gives 2

Example: Counter CRDT

  • Operations: increment(), decrement()
  • Merge: Apply all operations (order doesn’t matter)
  • Result: All nodes converge to same count

State-based CRDTs replicate entire state and merge using a merge function.

State-based CRDT set: node states {a, b} and {b, c} merge by union into {a, b, c} with an idempotent, commutative merge

Example: Set CRDT (G-Set)

  • State: Set of elements
  • Merge: Union of sets
  • Result: All nodes converge to union of all additions

A PN-Counter (Positive-Negative Counter) tracks increments and decrements separately.

PN-Counter CRDT tracking per-node increments [2, 1, 0] and decrements [0, 1, 0], giving a value of 3 minus 1 equals 2

Merge: Element-wise maximum of increments and decrements vectors.


G-Set (Grow-Only Set): Only allows additions, never removals.

Grow-only G-Set CRDT: Node 1 adds a and b, Node 2 adds b and c, and the union merge converges all nodes to {a, b, c}

2P-Set (Two-Phase Set): Tracks additions and removals separately.

Two-phase 2P-Set CRDT with added set {a, b, c} and removed set {b}, so the resulting set is {a, c}

LWW-Register uses last-write-wins with timestamps.

LWW-Register CRDT: writes of x = 100 at T1 and x = 200 at T2 merge by timestamp, so x = 200 wins

Note: LWW-Register is a CRDT but still loses data (same problem as LWW strategy).


How conflict resolution affects your class design:

💡 Tip: Click dropdown to switch between languages
Last-Write-Wins
from datetime import datetime
from typing import Optional
class LWWRegister:
def __init__(self, value=None):
self.value = value
self.timestamp: Optional[datetime] = None
def write(self, value):
self.value = value
self.timestamp = datetime.now()
def merge(self, other: 'LWWRegister') -> 'LWWRegister':
# Last write wins
if other.timestamp and (not self.timestamp or other.timestamp > self.timestamp):
return LWWRegister(other.value, other.timestamp)
return LWWRegister(self.value, self.timestamp)
💡 Tip: Click dropdown to switch between languages
Vector Clock
from typing import Dict, List
class VectorClock:
def __init__(self, node_id: int, num_nodes: int):
self.node_id = node_id
self.clock = [0] * num_nodes
def tick(self):
# Increment own timestamp
self.clock[self.node_id] += 1
def update(self, other: 'VectorClock'):
# Merge: element-wise maximum
for i in range(len(self.clock)):
self.clock[i] = max(self.clock[i], other.clock[i])
def happened_before(self, other: 'VectorClock') -> bool:
# Check if self happened before other
all_le = all(self.clock[i] <= other.clock[i] for i in range(len(self.clock)))
any_lt = any(self.clock[i] < other.clock[i] for i in range(len(self.clock)))
return all_le and any_lt
def concurrent(self, other: 'VectorClock') -> bool:
# Check if concurrent (conflict)
return not self.happened_before(other) and not other.happened_before(self)
💡 Tip: Click dropdown to switch between languages
G-Set CRDT
from typing import Set
class GSet:
"""Grow-Only Set CRDT - only allows additions"""
def __init__(self):
self.elements: Set = set()
def add(self, element):
# Only addition allowed
self.elements.add(element)
def merge(self, other: 'GSet') -> 'GSet':
# Merge: union of sets (commutative, associative)
merged = GSet()
merged.elements = self.elements.union(other.elements)
return merged
def contains(self, element) -> bool:
return element in self.elements

Choosing a conflict strategy: last-write-wins for caches, vector clocks for chat and comments, CRDTs for counters and sets
StrategyProsConsUse Cases
LWWSimpleData lossCache, non-critical data
Vector ClocksDetects conflicts, preserves causalityComplexChat, comments, collaborative editing
CRDTsNo conflicts, automatic mergeLimited operationsCounters, sets, collaborative editing

Company: Twitter, GitHub, Stack Overflow

Scenario: Caching user session data, API responses, and frequently accessed data. Multiple cache servers update the same key simultaneously.

Implementation: Uses Last-Write-Wins (LWW) strategy:

Redis cache last-write-wins: two cache servers write user:123 as Alice then Bob, the later Bob wins and losing Alice is acceptable

Why LWW? Cache data is non-critical and can be regenerated. Simplicity and performance matter more than preserving all writes.

Real-World Impact:

  • Twitter: Uses Redis with LWW for caching tweet metadata
  • Performance: Sub-millisecond cache updates
  • Data Loss: Acceptable since cache can be repopulated from database

Example 2: Slack/Discord Chat Messages (Vector Clocks)

Section titled “Example 2: Slack/Discord Chat Messages (Vector Clocks)”

Company: Slack, Discord, Microsoft Teams

Scenario: Chat messages must be delivered in causal order. If User A sends a message, and User B replies, the reply must appear after the original message, even if messages arrive out of order.

Implementation: Uses Vector Clocks to track causal relationships:

Slack-style chat with vector clocks: Hello is delivered first, then concurrent replies Hi there and Hey in the order received

Why Vector Clocks? Chat applications need to preserve causality (replies after original messages) and detect concurrent edits. Users expect messages in logical order.

Real-World Impact:

  • Slack: Uses vector clocks for message ordering across distributed servers
  • Reliability: 99.9% correct message ordering even during network partitions
  • User Experience: Messages appear in logical order, not arrival order

Example 3: Google Docs Collaborative Editing (CRDTs)

Section titled “Example 3: Google Docs Collaborative Editing (CRDTs)”

Company: Google, Notion, Figma

Scenario: Multiple users edit the same document simultaneously. Each character insertion/deletion must be preserved, and all users must see the same final document.

Implementation: Uses CRDTs (Operation-Based) for text editing:

Google Docs style operation-based CRDT: two users' character insert operations for Hi and Hey merge and converge regardless of order

Why CRDTs? Collaborative editing requires automatic conflict resolution. CRDTs ensure all replicas converge to the same state without manual conflict resolution.

Real-World Impact:

  • Google Docs: Uses CRDTs (specifically, Operational Transformation) for collaborative editing
  • Scalability: Supports 50+ simultaneous editors on the same document
  • Consistency: All users see the same document state within seconds

Example 4: DynamoDB Conflict Resolution (Last-Write-Wins with Vector Clocks)

Section titled “Example 4: DynamoDB Conflict Resolution (Last-Write-Wins with Vector Clocks)”

Company: Amazon DynamoDB

Scenario: Key-value store where multiple clients update the same key. System needs to detect conflicts and resolve them.

Implementation: Uses LWW-Register CRDT with vector clocks for conflict detection:

DynamoDB conflict handling: vector clocks [1,0] and [0,1] detect concurrent writes, then last-write-wins picks Bob

Why Hybrid Approach? DynamoDB uses vector clocks to detect conflicts, then applies LWW for resolution. This provides conflict detection (vector clocks) with simple resolution (LWW).

Real-World Impact:

  • Amazon: DynamoDB handles millions of concurrent writes
  • Conflict Rate: <0.01% of writes result in conflicts
  • Performance: Sub-10ms conflict resolution latency

Example 5: Riak Distributed Database (CRDTs)

Section titled “Example 5: Riak Distributed Database (CRDTs)”

Company: Riak (Basho Technologies)

Scenario: Distributed key-value database where multiple nodes update the same key independently. System must converge to consistent state.

Implementation: Uses State-Based CRDTs (G-Set, PN-Counter, etc.):

Riak state-based counter CRDT: three nodes merge by element-wise maximum of increment and decrement vectors to a converged value of 3

Why State-Based CRDTs? Riak prioritizes automatic convergence and conflict-free replication. CRDTs ensure all nodes eventually see the same state without manual intervention.

Real-World Impact:

  • Riak: Used by companies like GitHub, Comcast for distributed storage
  • Convergence: All replicas converge within seconds of network healing
  • Reliability: 99.99% data consistency guarantee


Congratulations! You’ve completed the Consistency & Distributed Transactions section. You now understand:

  • Consistency models (strong, eventual, causal)
  • CAP theorem (the fundamental trade-off)
  • PACELC theorem (adding latency considerations)
  • Distributed transactions (2PC, Saga pattern)
  • Conflict resolution (LWW, vector clocks, CRDTs)

Next up: Explore how these concepts apply to Database & Storage Systems — Learn about ACID properties, isolation levels, and database scaling.