Skip to content
Low Level Design Mastery Logo
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.

Diagram

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

Diagram

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

Diagram Diagram
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.

Diagram Diagram

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

Diagram

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.

Diagram

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”).

Diagram

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.

Diagram

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.

Diagram

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


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

Diagram

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

Diagram

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

Diagram

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


How conflict resolution affects your class design:

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)
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)
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

Diagram
StrategyProsConsUse Cases
LWWSimpleData lossCache, non-critical data
Vector ClocksDetects conflicts, preserves causalityComplexChat, comments, collaborative editing
CRDTsNo conflicts, automatic mergeLimited operationsCounters, sets, collaborative editing


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.