8 min read
System Design Index
Start Here
Tier 1 -- Building Blocks
Scale Reads
Scale Writes
Database Selection
Traffic Control
Consistency & Coordination
Estimation
Tier 2 -- Core Systems
Tier 3 -- Location & Real-Time
Tier 4 -- Infrastructure & Data
Tier 5 -- Finance & Commerce
Tier 6 -- Advanced & Collaborative
System Design Index
Start Here
Tier 1 -- Building Blocks
Scale Reads
Scale Writes
Database Selection
Traffic Control
Consistency & Coordination
Estimation
Tier 2 -- Core Systems
Tier 3 -- Location & Real-Time
Tier 4 -- Infrastructure & Data
Tier 5 -- Finance & Commerce
Tier 6 -- Advanced & Collaborative
Read Replicas & Read/Write Separation
Tier 1 — Building Block
1. What Is It?
A is a copy of a primary (leader) database that receives a continuous stream of changes from the primary and can serve read queries. The primary handles all writes; replicas handle reads. This is also called read/write separation or leader-follower .
Without read replicas, a single database node handles both writes (which require durable commits and locking) and reads (which scan indexes and return results). At scale, these workloads compete for the same CPU, memory, and I/O budget. Read replicas separate these concerns: writes go to the primary, reads are distributed across one or more replicas, multiplying read horizontally.
The tradeoff is lag: replicas receive changes asynchronously (usually), meaning they may lag the primary by milliseconds to seconds. Reads from replicas can return stale data.
Your e-commerce platform is experiencing performance degradation because product catalog browsing (reads) and order processing (writes) are competing for the same database resources. Which of the following best describes why adding read replicas would help this specific situation?
2. How It Works
Replication Mechanism
- Primary receives a write (INSERT, UPDATE, DELETE).
- Primary writes the change to its Write-Ahead Log () (PostgreSQL) or binlog (MySQL) before committing.
- A stream ships /binlog entries to each replica in near-real-time.
- Each replica applies the log entries to its own data files, staying in sync with the primary.
Read/Write Routing
The application (or a proxy like PgBouncer, ProxySQL, RDS Proxy) must route queries to the correct endpoint:
INSERT/UPDATE/DELETE/BEGIN TRANSACTION→ Primary connection stringSELECT(that tolerates stale data) → ReplicaSELECT(immediately after a write, must be fresh) → Primary, or use read-your-writes consistency technique
Replication Modes
- Asynchronous (default in MySQL, PostgreSQL): Primary commits immediately; WAL is sent to replicas without waiting for acknowledgment. Fastest writes; small lag window (~10ms–1s typically, can be longer under load).
- Synchronous: Primary waits for at least one replica to durably persist the change — and, in the strictest mode (PostgreSQL
synchronous_commit = remote_apply), to apply it so it is visible to queries on that replica — before committing. Zero data loss; higher write (~+10ms RTT per synchronous replica). - Semi-synchronous (MySQL): Primary waits only for at least one replica to receive the entry into its relay log (not apply it) before committing. Balances and .
A user submits a checkout form that creates a new order, and the very next request immediately fetches that order to display a confirmation page. Your backend routes all SELECT queries to a read replica by default. What problem could arise, and how should it be handled?
3. Variants & Comparisons
| Configuration | Consistency | Write Latency | Read Scalability | Failure Behavior |
|---|---|---|---|---|
| Single Primary, No Replicas | Strong | Fast | Limited to one node | Primary down = full outage |
| Async Replicas | Eventual (lag: 10ms–1s) | Fast (no wait) | Scales horizontally | Replica down = reads to others; primary down = possible data loss if async replica promoted |
| Sync Replica (1 standby) | Strong (primary + standby) | +RTT latency per write | One additional read node | No data loss on failover to synced standby |
| Multi-Region Replicas | Eventual (lag: 50ms–500ms) | Fast locally | Global read distribution | Serves reads during regional outage; writes fail if primary region is down |
| Multi-Primary (Multi-Master) | Eventual (conflict resolution required) | Fast | Full read+write scale | Complex conflict resolution; risk of split-brain |
Specific Technologies:
- PostgreSQL Streaming : Native async/sync physical . -level replication. Exact byte-for-byte copy of primary. Managed versions: AWS RDS/Aurora (Aurora replicas have ~10ms lag), GCP Cloud SQL, Azure Database.
- MySQL Group Replication / InnoDB Cluster: Semi-sync replication, supports automatic failover. Used by MySQL Router for read/write splitting.
- AWS Aurora: Custom replication protocol with shared storage layer. Up to 15 read replicas with <10ms lag. Failover in ~30 seconds. Aurora Global Database for cross-region replicas (60ms+ lag typical).
- Vitess (YouTube/PlanetScale): + replication management layer for MySQL. Used by YouTube, Slack, GitHub. Handles read/write routing and pooling at massive scale.
- PgBouncer / ProxySQL: Connection poolers that also route queries — ProxySQL can automatically send writes to primary and reads to replicas using query analysis rules.
Your team is deploying a write-heavy e-commerce platform globally. Stakeholders want users in Europe and Asia to experience fast reads, and the engineering team is comfortable accepting some read staleness. However, if the primary region goes down, the business can tolerate a brief window where writes fail — but reads must continue being served. Which replication configuration best fits these requirements?
4. When to Use It (and When NOT To)
Use Read Replicas When:
- Read-to-write ratio > 5:1: Most web apps are read-heavy (product listings, profile pages, feed queries)
- Primary DB CPU > 60% from reads: Reads are starving write
- Analytics/reporting queries: Long-running
SELECTscans can block or compete with OLTP; route them to a dedicated reporting replica - Geographic distribution: Put a replica in each region to serve local reads with low (e.g., US replica for US users, EU replica for EU users)
- : A synchronous standby replica means zero data loss on primary failure
Decision triggers:
- "If your read QPS > 70% of DB capacity → add read replicas"
- "If you have reporting workloads running on the same DB as OLTP → add a dedicated analytics replica"
- "If you need <10ms reads from multiple geographies → add regional replicas"
Do NOT Use Read Replicas When:
- Strong read-after-write consistency required: After writing a record, user immediately reads it — if routed to a replica, they may see stale data. Fix: route such reads to primary, or use sync replica.
- lag is unacceptable: Financial balances, inventory counts during checkout — even 100ms stale data causes correctness issues. Use primary for these reads.
- Write-heavy workload: Replicas help with reads; if your bottleneck is write , you need , not replicas.
Anti-patterns:
- Reading from replica immediately after write without a read-your-writes mechanism — users see their own write disappear.
- Ignoring lag — lag can grow under write spikes; replica may fall significantly behind without .
- Using replicas for distributed transactions — transactions that span primary + replica are not atomic.
An e-commerce platform processes orders at checkout. When a user adds an item to their cart, the inventory count is immediately decremented in the database. The checkout service then reads the inventory count to verify stock availability before confirming the order. The team is considering routing these inventory reads to a read replica to reduce load on the primary database. Why is this a poor choice?
5. Real-World Usage
GitHub (MySQL with Vitess): GitHub serves ~100M read queries/day from MySQL read replicas. They use ProxySQL to route reads to replicas and writes to the primary. A critical pattern they document: "read-your-writes" is implemented by recording the binlog position after each write; subsequent reads are directed to the primary until the replica reports it has caught up to that position.
Instagram (PostgreSQL + Django): Instagram used Django's multiple database routing to direct reads to PostgreSQL replicas. Their 2012 engineering blog describes scaling to ~25M users with a primary + 2 async replicas per shard, routing 90% of reads to replicas. lag was acceptable because most reads (photo feeds, profile views) tolerate .
AWS Aurora Multi-AZ: Aurora maintains one primary and up to 15 replicas using a shared distributed storage layer (not traditional shipping). Because all replicas read from the same storage layer, lag is <10ms — much lower than traditional async replication. This is how Aurora achieves "fast local reads with replica consistency."
A user posts a new comment on your platform, which is backed by a primary database and several async read replicas. Immediately after posting, the user is redirected to a page that reads their own comment back from the database. To avoid showing the user a 'missing' comment due to replication lag, which strategy should your system use?
6. Interview Cheat Sheet
Key sentences to demonstrate depth:
- "Read replicas multiply read horizontally — each replica is an independent read node, so N replicas give you N× read capacity."
- "The fundamental tradeoff is lag: async replicas are ~10ms–1s behind the primary. For most reads (feed queries, product listings, profile views), this is acceptable. For reads immediately after writes, I route to the primary."
- " lag can become a serious problem under write bursts — if the primary is writing 50K rows/sec and a replica falls behind, it could be minutes behind. You need lag and ."
- "A synchronous standby replica costs you write (must wait for replica ACK) but gives you zero data loss on failover — worth it for financial or critical data."
- "Read replicas solve read , not write throughput. If writes are the bottleneck, I need — replicas don't help there."
Common follow-up questions:
| Question | Concise Answer |
|---|---|
| "What is replication lag?" | The time between when the primary commits a write and when a replica has applied it. Typically 10ms–100ms async; can grow to minutes under write spikes. |
| "How do you handle read-your-writes?" | Option 1: Route all reads immediately after a write to the primary. Option 2: Track replication position (LSN/GTID) after each write; route reads to replica only when replica has caught up. |
| "What happens when the primary fails?" | A replica must be promoted to primary (manual or automatic via tools like Patroni, MHA, AWS RDS Multi-AZ). With async replication, any un-replicated writes may be lost. |
| "How do you avoid replica lag growing?" | Monitor replica lag metric; set alerting threshold (e.g., >5s = page). Reduce write throughput or add more powerful replicas. Consider sync replication for critical data. |
| "Why not just shard instead of using replicas?" | Sharding adds significant complexity (cross-shard queries, distributed transactions, shard key choice). Replicas are simpler — use them first; shard when writes become the bottleneck. |
Connections to other building blocks:
- Caching Strategies: Complementary to caching. Cache handles repeated reads of the same objects; replicas scale diverse query patterns. Use both: cache for hot keys, replicas for query load.
- & : Read replicas scale read throughput; sharding scales write throughput. A fully scaled system often uses both: shards, each shard having replicas.
- Write-Ahead Log (): Replication is fundamentally built on the . The replica is a consumer of the primary's WAL stream.
- CAP Theorem: Async replicas = AP (, ). Sync replicas with = CP (, lower under network partition).
- Load Balancing: The read in front of replicas distributes read traffic; it needs health checking to avoid routing to a lagged or failed replica.
Glossary History
Click dotted jargon to save explanations here.
Glossary History
Click dotted jargon to save explanations here.