Lesson 58 of 105 12 minFlagship

System Design: Multi-Leader Database Replication

How to handle writes across multiple data centers. A deep dive into multi-leader replication, conflict resolution strategies (LWW, CRDTs), and data consistency.

Reading Mode

Hide the curriculum rail and keep the lesson centered for focused reading.

Key Takeaways

  • **Geo-Latency:** Users in London write to the London datacenter; users in NYC write to the NYC datacenter.
  • **Resilience:** If one datacenter goes down, others can still accept writes.
  • **Scalability:** Horizontal write scaling.
Recommended Prerequisites
System Design Interview Framework

Premium outcome

From vague architecture answers to staff-level trade-off thinking.

Backend engineers preparing for senior, staff, and architecture rounds.

What you unlock

  • A reusable system design answer framework for ambiguous prompts
  • Clear language for consistency, scaling, and reliability trade-offs
  • Case-study depth across feeds, payments, storage, and messaging systems

Mental Model

Single-leader replication guarantees write order but bottlenecks on a single geographic location. Multi-leader replication enables localized, sub-millisecond writes globally, but introduces the hard constraint of distributed write-conflict reconciliation. You are trading write simplicity for geographical write scalability.


Requirements and System Goals

When designing active-active state replication across global datacenters, we must align our system boundaries to strict operational limits.

1. Functional Requirements

  • Global Geographic Write Path: Users in any geographic region (e.g., US-East, EU-West, AP-South) must write to their closest local database replica.
  • Bi-Directional State Synchronization: Changes made in US-East must replicate asynchronously to EU-West, and vice-versa, converging to a unified state.
  • Offline Operation Capability: Support for clients to perform writes locally on disconnected nodes (e.g., mobile apps) and sync back when connected.

2. Non-Functional Requirements & Latency Budgets

  • Ultra-Low Local Write Latency: Local database writes must return inside a P99 latency budget of less than 10ms.
  • Replication Lag tolerance: The system must tolerate inter-datacenter replication delays (typically 100ms - 500ms depending on cross-ocean WAN fibers).
  • Availability Target: "Five Nines" (99.999%) write availability. The database must remain writeable even if a whole region goes completely offline.

3. Back-of-the-Envelope Estimation: WAN Replication Bandwidth

To properly size our inter-region network links and write queues, we calculate the required bandwidth for real-time synchronization.

  • Write Traffic Model:
    • Assume our global system processes 50,000 writes/second at peak.
    • Average raw user profile write payload size is 1 KiB.
  • Replication Metadata Overhead:
    • Each write payload is wrapped with version vector metadata, transactional identifiers, and lineage tags, adding 500 bytes of replication headers.
    • Total payload size per write during replication = 1.5 KiB.
  • Bandwidth Calculations:
    • Peak Write Volume: $50,000 \times 1.5 \text{ KiB} = 75,000 \text{ KiB/s}$.
    • Convert to Megabits per second (Mbps): $75,000 \text{ KiB/s} \times 8 \text{ bits/byte} \div 1,024 \approx 586 \text{ Mbps}$.
    • To prevent queue backlog during spikes, we apply a $2.5\times$ safety headroom factor, requiring a dedicated WAN interconnect pipeline capacity of at least 1.46 Gbps between our primary data centers.
    • Queue Buffer Requirements: If the WAN link suffers a total partition for 30 minutes, the local queue must buffer: $50,000 \text{ writes/s} \times 1800 \text{ seconds} = 90,000,000 \text{ write events}$. At $1.5 \text{ KiB}$ per write, this requires a local persistent memory or fast NVMe storage pool of at least 128.7 GiB per replication node to absorb the backlog without spilling or dropping messages.

API Interfaces and Service Contracts

To demonstrate data ingestion and synchronization, we define the RESTful contract representing user state updates and the internal replication synchronization schema.

1. Client Profile Write Endpoint

POST /api/v1/users/profile

Request Payload:

{
  "userId": "usr_9921b",
  "displayName": "Alice Smith",
  "version": 4,
  "lastUpdated": 1779983200000
}

2. Inter-Datacenter Replication Contract

When a datacenter replicates a write to its peer, it appends version vector metadata to allow logical clock synchronization and conflict identification.

Replication Payload:

{
  "eventId": "evt_9981a-88cd",
  "sourceDatacenter": "US-EAST",
  "userId": "usr_9921b",
  "payload": {
    "displayName": "Alice Smith",
    "version": 4
  },
  "versionVector": {
    "US-EAST": 12,
    "EU-WEST": 8
  },
  "timestamp": 1779983200000
}

3. Client Read-After-Write Consistency Contract

Because replication is asynchronous, a client writing to US-East might immediately read from EU-West (due to dynamic geographical load-balancing or traveling users) and receive stale data. To solve this, our gateway returns a transaction token, and clients can request a read with a minimum logical state constraint.

GET /api/v1/users/profile?userId=usr_9921b

Headers: X-Min-Logical-State: {"US-EAST": 12, "EU-WEST": 8}

If the local read replica's internal logical clock has not reached these numbers, the gateway routing service pins the client's read back to the source datacenter (US-East) or blocks the read briefly until the local database's asynchronous queue catches up.


High-Level Design and Visualizations

Let's visualize the active-active multi-leader architecture spanning two geographical regions.

graph TD
    subgraph US_East [US-East Datacenter]
        Client_US((US Clients)) --> DNS_US[Geo-DNS Router]
        DNS_US --> LB_US[Load Balancer]
        LB_US --> App_US[US App Servers]
        App_US --> DB_US[(US Leader DB)]
    end
    
    subgraph EU_West [EU-West Datacenter]
        Client_EU((EU Clients)) --> DNS_EU[Geo-DNS Router]
        DNS_EU --> LB_EU[Load Balancer]
        LB_EU --> App_EU[EU App Servers]
        App_EU --> DB_EU[(EU Leader DB)]
    end
    
    %% Async Replication Queue over WAN
    DB_US <-->|Async Replication Queue over WAN| DB_EU

Low-Level Design and Schema Strategies

In a multi-leader database replication scheme, standard autoincrementing integer primary keys (SERIAL) are an immediate system failure vector. If US-East and EU-West both write a new user, they will both generate id = 1, causing primary key collisions during replication.

1. The Multi-Master Database Schema

To prevent collisions, we use universally unique identifiers (UUIDv7) and embed version vector tracking columns.

-- Database schema for active-active multi-leader replication
CREATE TABLE user_profiles (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    display_name VARCHAR(100) NOT NULL,
    version INT NOT NULL DEFAULT 1,
    
    -- Telemetry & Conflict Resolution Columns
    last_updated_at TIMESTAMP WITH TIME ZONE NOT NULL,
    origin_datacenter VARCHAR(20) NOT NULL,
    
    -- Version Vector representation serialized as JSONB
    -- Example format: {"US-EAST": 12, "EU-WEST": 8}
    version_vector JSONB NOT NULL
);

-- Indexing for lookup speed and background sync reconciliations
CREATE INDEX idx_profiles_updated ON user_profiles(last_updated_at DESC);

2. UUIDv7 Byte Layout Optimization

UUIDv7 is specifically chosen because it embeds a highly millisecond-precise Unix timestamp in its first 48 bits, followed by 4 bits of sub-millisecond counter and 74 bits of random entropy.

  • Why B-Tree Indexes Love UUIDv7: Traditional UUIDv4 is completely random, which causes severe write amplification. When inserting UUIDv4 keys into a database B-Tree index, the inserts hit random leaf nodes, triggering constant leaf splitting, page fragmentation, and massive cache misses.
  • Sequential Monotonicity: UUIDv7 keys are naturally sequential. As new profiles are inserted in either datacenter, the keys are monotonically increasing, meaning they are appended directly to the rightmost leaf of the database B-Tree index. This maintains index density, keeps page splits to a minimum, and maximizes write throughput.

Scaling and Operational Challenges

1. Write Conflict Resolution Strategies

When writes occur concurrently in separate datacenters, conflicts are inevitable. Let's analyze the mathematical and algorithmic approaches to resolving them.

A. Last Write Wins (LWW)

The system discards any write with an older physical timestamp.

  • Complexity: $O(1)$
  • Trade-off: High risk of data loss. A clock drifted 20ms backward in one region will cause real writes to be silently deleted. LWW should only be used when minor data loss is completely acceptable, such as tracking anonymous user clickstream counts.

B. Conflict-Free Replicated Data Types (CRDTs)

Specialized mathematical data structures where operations commute—meaning they can be applied in any order and will always merge to the exact same state.

  • Grow-Only Counter (G-Counter): Each replica tracks increment actions. Replicas merge counters by taking the maximum value.
  • Positive-Negative Counter (PN-Counter): Extends G-Counters by maintaining an addition vector and a subtraction vector. The total count is calculated by subtracting the subtraction vector from the addition vector.
  • LWW-Element-Set: Replicas maintain an add-set and a remove-set, resolving overlaps using operation timestamps.

C. Version Vectors and Causality Detection

Each node increments its entry in a version vector upon performing a local write. When comparing two states with version vectors $V_1$ and $V_2$:

  • $V_1$ dominates $V_2$ ($V_1 > V_2$) if for every element $k$, $V_1[k] \ge V_2[k]$ and at least one element is strictly greater. This means $V_1$ is a causally descended successor of $V_2$.
  • If neither dominates (e.g., $V_1[\text{US}] > V_2[\text{US}]$ but $V_1[\text{EU}]$ is less than $V_2[\text{EU}]$), a concurrent write conflict is detected. The application must invoke custom resolution logic (e.g., merging strings or prompting the user).

Architectural Trade-offs and Topology Decisions

The topology of the replication network significantly dictates write propagation latency and fault tolerance bounds.

Topology Dimension Circular Ring Topology Star Topology All-to-All Mesh Topology
Visual Flow A $\rightarrow$ B $\rightarrow$ C $\rightarrow$ A Central Hub $\leftrightarrow$ Spokes Every node $\leftrightarrow$ Every node
Write Hop Count High ($N-1$ hops for full sync) Medium (Always exactly 2 hops) Low (Exactly 1 hop)
Resilience to Node Failure Poor (A single failed node breaks replication) Poor (Hub failure completely halts sync) High (Sync routes around dead nodes)
Replication Loop Risk High (Requires tag validation to stop loops) Low (Central hub regulates routes) High (Requires tracking unique write IDs)
graph TD
    subgraph Ring Topology
        R1[Node A] --> R2[Node B]
        R2 --> R3[Node C]
        R3 --> R1
    end
    
    subgraph Star Topology
        S_Hub((Central Hub)) <--> S1[Node A]
        S_Hub <--> S2[Node B]
        S_Hub <--> S3[Node C]
    end
    
    subgraph All-to-All Mesh Topology
        M1[Node A] <--> M2[Node B]
        M2 <--> M3[Node C]
        M3 <--> M1
    end

Failure Modes and Fault Tolerance Strategies

1. The Split-Brain Reconciliation Failure

Under a network partition where the US-East and EU-West WAN link is completely severed:

  • Both regions remain online and continue accepting writes (high availability).
  • Version vectors diverge as each region records writes without receiving peer syncs.
  • The Reconciliation Storm: Once the WAN link heals, millions of conflicting updates are queued for delivery simultaneously.
  • Staff Mitigation: Implement strict Rate-Limiting on Replication Queues during WAN healing. Process reconciliation batches asynchronously, utilizing background worker queues (like Celery or custom thread pools) to prevent primary database lock starvation.

2. Replication Loops

In a circular or mesh topology, when Node A sends a write to Node B, Node B might replicate it to Node C, which then attempts to replicate it back to Node A, causing an infinite write storm.

  • Mitigation: Every replicated write must be tagged with an origin_node_id. When a node receives a write where the origin matches its own ID, it silently discards the write, terminating the propagation loop.

3. Cascading Replication Queue Bloat

When an entire datacenter goes offline or suffers a severe network partition, replication traffic destined for it cannot be delivered. In-memory queues in the healthy datacenters start storing these outbound messages, leading to rapid memory consumption.

  • The Danger: If the outbound replication queue is unbounded, the healthy databases will suffer a JVM garbage collection freeze or an Out-Of-Memory (OOM) crash, taking down the remaining healthy regions.
  • Staff Mitigation: Configure strict, bounded disk-backed queues (e.g., using RocksDB or persistent disk queues) for cross-datacenter replication. When the queue size reaches 80% of disk capacity, drop replication messages to protect node survival, marking the destination datacenter as "desynchronized." Once connectivity is restored, trigger an active anti-entropy background job (such as a Cassandra-style nodetool repair using Merkle Trees) to reconstruct the missing data partitions incrementally.

Staff Engineer Perspective


Production Readiness Checklist

Before moving an active-active multi-leader database into production, verify:

  • Conflict Avoidance Active: Users are strictly partitioned to write to a single home datacenter based on Geo-DNS routing, preventing 99% of concurrent write paths.
  • UUID v7 Primary Keys: All database tables use UUIDs or Snowflake IDs to prevent auto-increment integer key collisions.
  • NTP Clock Drift Monitored: Chrony or NTP alerts are configured with a strict threshold of less than 10ms drift before taking a database replica out of the active write pool.
  • Version Vectors Serially Mapped: Application schemas store and increment logical vectors correctly on every database update.


Verbal Script

Interviewer: "How would you handle write conflicts in a multi-region active-active system design?"

Candidate: "To handle write conflicts in an active-active multi-leader architecture, my first step is Conflict Avoidance. The simplest way to handle conflict is to prevent it from ever happening. I would configure our Geo-DNS routing and load balancers to route users based on their location, ensuring that a specific user always writes to their 'home' region database replica. This eliminates 99% of concurrent write collisions.

However, for cases where concurrent writes are unavoidable—such as two users concurrently editing a shared document across regions—we must employ strict algorithmic resolution.

I would avoid basic Last Write Wins (LWW) because cross-region NTP clock skew can cause real data to be silently deleted. Instead, I would utilize Version Vectors to track causality. Every node stores and updates a logical clock vector. On sync, if the incoming vector dominates our local vector, we apply the change. If the local vector dominates the incoming one, we discard it. If they overlap, indicating concurrent writes, we invoke application-specific merge strategies—or use Conflict-Free Replicated Data Types (CRDTs) like LWW-Element-Sets or G-Counters to resolve the conflicts deterministically.

Finally, at the database layer, I would enforce the use of UUIDv7 primary keys to prevent numerical ID collisions, and use replication queues equipped with rate limiters to handle reconciliation storms when network partitions heal."

Want to track your progress?

Sign in to save your progress, track completed lessons, and pick up where you left off.