Fun with Learning Technology
LearnCoursesQuestionsTracksToolsNewsExplorePractice
Fun with Learning Technology

A new problem, explained clearly, every day.

Subscribe
Learn
  • Lessons
  • Topics
  • News
  • Tools
  • Courses
  • Career tracks
  • Everything
Site
  • About
  • Contact
  • Support
  • Privacy
  • Terms
Get the daily one

One email per new problem. No spam.

Request a tutorial

Requests shape what gets made next.

© 2026 Fun with Learning TechnologyRSS
Home›Courses›System Design›Database Replication

Databases

Database Replication

Database replication is the process of copying data from one primary database server to one or more secondary replicas to ensure data availability and fault tolerance. It is essential for scaling read-heavy workloads and providing failover mechanisms during server outages. You reach for replication whenever your system demands high availability, geographic data distribution, or the ability to scale read queries independently of write operations.

Single-Leader Replication

Single-leader replication is the foundational architecture where all write operations must pass through a single primary node, while reads can be distributed across various follower nodes. The primary node is responsible for processing incoming write requests and propagating these changes to its replicas. Because only one node handles writes, the system avoids complex conflict resolution scenarios that arise in multi-master setups, making it the most predictable model for most applications. When a write occurs on the primary, it logs the change and ships it to followers, which then update their own local storage. The delay between the primary update and the follower update is known as replication lag. This lag is a critical design constraint, as it means followers may briefly show stale data. Understanding this trade-off is fundamental to designing distributed systems that balance consistency and performance.

# Simple simulation of primary write and log propagation
class DatabaseNode:
    def __init__(self, name): self.name = name; self.data = {}
    def write(self, key, value):
        self.data[key] = value
        print(f"{self.name} updated: {key}={value}")

primary = DatabaseNode("Primary")
replica = DatabaseNode("Replica-1")

# Synchronous write propagation
primary.write("user_id", 101)
replica.write("user_id", 101) # Simulated replication log applying change

Handling Replication Lag

Replication lag is the unavoidable temporal gap between the primary database committing a transaction and a follower applying the same change. In high-traffic systems, this window can grow, causing users to see stale data. A common symptom is 'read-your-own-writes' inconsistency, where a user updates their profile but sees the old version upon refreshing because their read request was routed to a lagging replica. To mitigate this, developers can implement session-based routing, ensuring a user's reads are directed to the primary for a short period after they perform a write. Alternatively, one can check the replica's replication status against the primary's last applied log index before serving a request. By understanding that replicas are eventually consistent, you can design application logic that handles these minor delays gracefully rather than assuming real-time global consistency across all database nodes.

# Check if replica is caught up before allowing read
def get_user_data(replica, replica_lsn, primary_lsn):
    # Compare Log Sequence Numbers (LSN) to ensure freshness
    if replica_lsn < primary_lsn:
        return "Error: Stale data, retrying on primary..."
    return replica.data.get("user_id")

# Simulating a scenario where replica is behind
print(get_user_data(replica, 10, 15)) # Returns stale error status

Multi-Leader Architectures

Multi-leader replication allows writes to occur on multiple nodes simultaneously, which is highly beneficial for geo-distributed systems where a user in Tokyo and a user in New York shouldn't have to wait for cross-continental round trips to perform a write. Each leader acts as a client to the other, asynchronously propagating write logs to keep nodes synchronized. The core complexity here is conflict resolution; if the same record is updated on two different leaders at roughly the same time, the system must reconcile the divergent states. Common strategies include 'last-write-wins' (using timestamps), or application-level conflict resolution where the system prompts the user to resolve the clash. While this architecture significantly improves write throughput and fault tolerance, it introduces significant complexity that must be managed by the application layer to maintain data integrity.

# Simulating conflict detection in multi-master
def update_record(node_id, key, value, timestamp):
    # Store value with timestamp for conflict resolution
    return {"val": value, "ts": timestamp}

node_a = update_record("A", "key1", "v1", 100)
node_b = update_record("B", "key1", "v2", 105) # Node B has a later timestamp

# Conflict resolution: Keep latest timestamp
final_state = node_b if node_b['ts'] > node_a['ts'] else node_a
print(f"Resolved state: {final_state['val']}")

Leaderless Replication

In leaderless replication, there is no designated primary node; instead, clients send write requests to multiple nodes in parallel. This decentralized approach removes the single point of failure inherent in single-leader models but complicates the process of reading data, as different nodes may contain conflicting versions of the same record. To handle this, reading is typically performed by querying a quorum of replicas. If you have five replicas and set your read quorum to three (R=3), you are statistically likely to receive the most recent version of the data. This requires nodes to store version vectors or timestamps to track the history of an object. Leaderless systems are exceptionally resilient and excel in environments where downtime is unacceptable, though they place the burden of reconciliation on the read-path logic and potentially return inconsistent results without proper quorum settings.

# Quorum read logic
def read_with_quorum(replicas, key):
    responses = [r.data.get(key) for r in replicas]
    # In a real system, return the value with the highest version/timestamp
    return max(responses, key=lambda x: x['version']) 

# Setup replicas with differing data
rep1 = {'data': {'val': 10, 'version': 1}}; rep2 = {'data': {'val': 10, 'version': 2}}
print(read_with_quorum([rep1, rep2], 'val'))

Failover and Consistency

Failover is the process of promoting a follower node to primary status when the current primary fails. This is a critical operation that must be handled with care to prevent 'split-brain' scenarios, where two nodes mistakenly believe they are the primary, leading to data corruption as they diverge. High-availability systems use consensus algorithms to manage the election of a new leader. Beyond failover, consistency models like 'strong consistency' ensure that once a write is acknowledged, all subsequent reads reflect that update, usually at the cost of latency. Systems often offer configurable consistency levels, allowing developers to choose between performance and strict accuracy. Designing a robust database layer requires mapping these replication strategies to your specific business requirements, ensuring that the cost of maintaining consistent data does not outweigh the benefits provided by the chosen replication architecture.

# Simple failover logic for leader election
class ClusterManager:
    def __init__(self, nodes):
        self.nodes = nodes
        self.primary = nodes[0]

    def failover(self):
        print(f"Primary {self.primary} down. Promoting new leader...")
        self.primary = self.nodes[1] # Simple promotion logic
        print(f"New primary is: {self.primary}")

manager = ClusterManager(["Node1", "Node2"])
manager.failover()

Key points

  • Replication is primarily used to increase read throughput and provide data redundancy.
  • Single-leader replication simplifies write operations but relies on a single point of failure.
  • Replication lag is the time difference between a write on the primary and an update on a follower.
  • Read-your-own-writes consistency can be achieved through session-based routing to the primary.
  • Multi-leader replication helps in geo-distributed scenarios but requires complex conflict resolution.
  • Leaderless systems use quorum-based reads and writes to ensure data availability without a primary.
  • Split-brain occurs when two nodes erroneously assume primary status during failover, causing data divergence.
  • Strong consistency trades off write latency to ensure all nodes see the same data at the same time.

Common mistakes

  • Mistake: Assuming database replication always provides strong consistency. Why it's wrong: Replication introduces lag, meaning read operations may return stale data. Fix: Use synchronous replication for strong consistency or design the application to handle eventual consistency.
  • Mistake: Thinking replication increases write throughput. Why it's wrong: In master-slave setups, writes must occur on the primary, often making it a bottleneck. Fix: Use sharding (partitioning) alongside replication to scale write operations.
  • Mistake: Neglecting the complexity of failover processes. Why it's wrong: Automated failover can lead to split-brain scenarios where two nodes think they are the leader. Fix: Implement consensus algorithms or health-check consensus services to manage leader election.
  • Mistake: Confusing replication with backups. Why it's wrong: Replication propagates accidental data deletion to all nodes instantly. Fix: Maintain point-in-time recovery snapshots independently of the active replication cluster.
  • Mistake: Failing to account for network latency in synchronous replication. Why it's wrong: Synchronous replication forces the primary to wait for acknowledgments, significantly increasing response time. Fix: Use asynchronous replication when high availability is more important than immediate consistency.

Interview questions

What is the primary purpose of database replication in a system design context?

Database replication is the process of copying data from one database server to one or more other servers. The primary purpose is to increase system availability, improve read performance, and provide fault tolerance. By distributing read requests across multiple replicas, we reduce the load on the primary node. Additionally, if the primary node experiences hardware failure, we can promote a replica to primary status, ensuring minimal system downtime and maintaining data accessibility for end users.

Can you explain how Single-Leader replication works?

In Single-Leader replication, all write requests are sent to a single designated primary node, which handles the write and updates its local storage. The primary then propagates these data changes to followers via a replication log. Followers process these updates asynchronously or synchronously and apply them to their local datasets. This model simplifies conflict resolution since there is only one source of truth, though it introduces a potential bottleneck at the primary node if write volume becomes extremely high.

What is the difference between synchronous and asynchronous replication?

Synchronous replication guarantees that the follower has successfully written the data before the primary acknowledges the write to the client. This ensures strong consistency, but it increases latency and reduces availability because a single slow follower can block the entire write pipeline. Asynchronous replication allows the primary to acknowledge writes immediately without waiting for followers. This provides higher performance and throughput but risks data loss if the primary crashes before the changes are propagated to the replicas.

How does Multi-Leader replication differ from Leaderless replication, and when would you choose one over the other?

Multi-Leader replication involves multiple nodes acting as leaders, where each leader accepts writes and propagates them to others, making it ideal for multi-datacenter setups to reduce write latency. Leaderless replication, such as in dynamo-style systems, allows any node to accept writes, often using quorum mechanisms (R+W > N) to ensure consistency. You choose Multi-Leader when you need high write availability across regions, whereas you choose Leaderless for high fault tolerance and the ability to handle network partitions gracefully.

What are the common challenges associated with replication lag?

Replication lag occurs when there is a delay between a write on the primary and the update appearing on a replica. This causes 'eventual consistency' issues, such as reading stale data or 'read-your-own-writes' violations, where a user updates a profile but doesn't see the change immediately upon refreshing. To mitigate this, developers might implement read-after-write consistency by routing a user to the primary node for their own data, or by using versioning to track whether a replica is sufficiently caught up.

Describe how conflict resolution is handled in Multi-Leader replication systems.

In Multi-Leader replication, conflicts occur when two users modify the same data simultaneously on different leaders. Since there is no single order of operations, the system must resolve these conflicts. Common strategies include Last-Write-Wins, which uses timestamps to pick the 'latest' change, or semantic merging, which stores both values and asks the application layer to reconcile them. Advanced systems may use conflict-free replicated data types (CRDTs) to mathematically ensure that all replicas converge to the same state regardless of the order in which updates are received.

All System Design interview questions →

Check yourself

1. When configuring a primary-replica architecture, why might an application choose asynchronous replication over synchronous replication?

  • A.To ensure all replicas have the most current data at all times.
  • B.To prevent any potential data loss during a primary node failure.
  • C.To minimize the latency impact on write operations.
  • D.To simplify the logic required for conflict resolution.
Show answer

C. To minimize the latency impact on write operations.
Synchronous replication requires waiting for confirmation from replicas, which increases write latency. Asynchronous replication avoids this wait, making it faster. The other options are incorrect because synchronous replication is better for consistency and data loss prevention, and neither mode inherently simplifies conflict resolution.

2. What is the primary risk associated with a 'split-brain' scenario in a multi-master replication setup?

  • A.Increased read latency due to heavy traffic on the secondary nodes.
  • B.Inconsistency caused by different nodes accepting conflicting writes.
  • C.Complete loss of data across all shards in the database cluster.
  • D.An infinite loop of replication traffic between the master nodes.
Show answer

B. Inconsistency caused by different nodes accepting conflicting writes.
A split-brain occurs when the network partition prevents nodes from communicating, leading them to accept independent, conflicting writes. The other options describe performance or storage issues, not the logical data divergence caused by split-brain.

3. Which strategy best addresses the problem of stale reads in a system using asynchronous replication?

  • A.Routing all read requests exclusively to the primary node.
  • B.Implementing a cache-aside pattern on top of the replicas.
  • C.Forcing the application to wait for an acknowledgment from all nodes.
  • D.Using read-your-writes consistency logic at the application layer.
Show answer

D. Using read-your-writes consistency logic at the application layer.
Read-your-writes consistency ensures that a user sees their own updates even if replicas lag, by routing the read to the primary or waiting for specific version tags. Routing to the primary is a valid architectural choice, but it doesn't solve the issue for the replication system itself, while option 3 is just synchronous replication.

4. In a Leader-Follower replication model, what is the effect of increasing the number of followers?

  • A.The system's write throughput capacity increases linearly.
  • B.The load on the primary node is significantly reduced for read-heavy workloads.
  • C.The time taken to elect a new leader during a failure is eliminated.
  • D.The likelihood of data conflicts during concurrent write operations is reduced.
Show answer

B. The load on the primary node is significantly reduced for read-heavy workloads.
Adding followers allows read traffic to be distributed, offloading the primary. Writes are still limited by the primary, so throughput doesn't increase linearly. Election time remains, and conflict frequency is unaffected because only one node writes.

5. Why is it dangerous to perform an automated failover without a consensus-based monitoring system?

  • A.It leads to excessive storage consumption on replica nodes.
  • B.It can trigger an accidental shutdown of the entire database cluster.
  • C.It may mistakenly promote a healthy node to leader while the old leader is still functioning.
  • D.It forces the system to switch to a write-only mode temporarily.
Show answer

C. It may mistakenly promote a healthy node to leader while the old leader is still functioning.
Without consensus, multiple nodes might 'think' the leader is dead and trigger elections, resulting in two leaders (split-brain). This causes massive data corruption. The other choices are either non-consequential or technically incorrect regarding how failover works.

Take the full System Design quiz →

← PreviousSQL vs NoSQL — When to Use WhichNext →Database Sharding and Partitioning

System Design

31 lessons, free to read.

All lessons →

Track your progress

Sign in to mark lessons done, score quizzes and keep notes.

Open in the app