Read Replicas Explained
Table of Contents + −
Think about an app like Twitter or a news site. Now ask yourself:
- How often does someone actually post something? Once in a while, right?
- How often do people scroll, refresh, and read posts? Constantly.
- So for most apps, reads happen way more than writes. Sometimes a hundred reads for every one write.
That imbalance is a clue. If almost all your traffic is reading, then maybe you can solve your scaling problem by getting better at reads. That’s exactly what read replicas do, and we’ll build up the idea one step at a time.
🎯 The Problem
Let’s picture a single database server handling everything for your app. Here’s where it starts to hurt:
- Every single request goes to that one machine. Reads, writes, all of it.
- As your app grows, the reads pile up. Thousands of people loading their feed, searching, opening pages.
- That one server gets buried. It’s spending almost all its energy answering read queries, and it has nothing left for anything else.
- So the whole app slows down, even though most of that traffic is just people reading the same kind of data.
The thing is, one machine can only do so much. You can give it a bigger CPU and more memory, but there’s a ceiling, and it gets expensive fast. We need a smarter way to spread out all those reads.
📖 What is a Read Replica
So here’s the core idea. A read replica is a read-only copy of your primary database that serves read queries. Let’s unpack that:
- Your main database, the one that handles writes, is called the primary (you’ll also hear it called the master or the leader).
- A read replica is a full copy of that primary’s data, kept on a separate server.
- It’s read-only, which means you can ask it for data but you cannot write to it. No inserts, no updates on a replica.
- And you can have many of them. One primary, and several replicas all holding the same data.
Think of it like a popular textbook in a library. There’s one official copy that gets updated, but the library makes photocopies so lots of students can read at the same time without fighting over the single original.
⚙️ How It Works
Now let’s see how the data stays in sync and how queries get sent to the right place. The flow goes like this:
- All writes go to the primary. When someone posts, signs up, or edits something, that change lands on the primary first.
- The primary then copies those changes out to every replica. This copying is called replication, and it happens continuously in the background.
- All reads get routed to the replicas instead of the primary. Loading a feed, viewing a profile, running a search, those go to a replica.
- Your app spreads reads across the replicas, so no single machine takes the whole load.
Here’s the picture. Writes flow into the primary, the primary feeds the replicas, and reads get split across those replicas.
So the primary has one clear job: handle writes and push changes out. The replicas have one clear job too: answer reads. Here’s a quick map of where each kind of query should go.
| Operation | Goes to | Why |
|---|---|---|
| Insert / Create | Primary | It’s a write, only the primary accepts writes |
| Update / Delete | Primary | Also a write, must hit the primary |
| Read a feed / page | Replica | Pure read, send it to a replica to spread load |
| Search / reports | Replica | Heavy reads, perfect for replicas |
⚡ Why Use Them
Okay, so why go through all this trouble of running extra database servers? A few solid reasons:
- You offload reads from the primary. Once the replicas handle all the read traffic, the primary is free to focus on writes. It stops being buried.
- You scale read-heavy apps easily. Getting more read traffic? Just add more replicas. Each new replica gives you more read capacity, and this is the big one for apps where reading dominates.
- You get a standby for free. Replicas already hold a full copy of your data. So if the primary crashes, you can promote a replica to become the new primary. That makes replicas double as a backup and a safety net.
Reads scale, writes don't (here)
Read replicas are a tool for scaling reads, not writes. Adding ten replicas gives you ten times the read power, but your write capacity stays exactly the same, because every write still goes to that one primary. Keep this in your head, it’s the whole point.
⚠️ Replication Lag and Stale Reads
Now here’s the catch, and it’s an important one. Copying data from the primary to the replicas isn’t instant. There’s a tiny delay. Let’s name it and see why it matters:
- That delay between a write landing on the primary and showing up on a replica is called replication lag. Usually it’s milliseconds, but under heavy load it can grow.
- During that gap, a replica is slightly behind. It has almost the latest data, just not the write that happened a moment ago.
- So if you write something and then immediately read it from a replica, you might not see your own change yet. The replica gives you the old value. That’s called a stale read, a read of data that’s a little out of date.
This shows up as a real bug for users. Picture Alex:
- Alex updates their profile name and hits save. The write goes to the primary.
- The page reloads and reads from a replica, but the replica hasn’t gotten the change yet.
- Alex sees the old name and thinks the save failed. Confusing, right?
This is the famous read your own writes problem, where a user should always see their own recent changes. Here’s how apps usually deal with it:
- Read from the primary right after a write. For a short window after someone writes, route their reads to the primary instead of a replica. They always see their own change.
- Wait for the replica to catch up before reading, when the app can afford a tiny pause.
- Accept the lag where it’s harmless. For something like a view count or a comment from a stranger, being a second behind is totally fine. Use replicas freely there.
Replicas are eventually consistent
A replica catches up to the primary “eventually”, usually in milliseconds, but not instantly. This is called eventual consistency. So never assume a replica has the very latest write the moment it happens. Design for the lag, don’t pretend it isn’t there.
🧩 When Read Replicas Aren’t Enough
Read replicas are great, but they hit a wall. Here’s where:
- They do nothing for write load. Every write still goes to the single primary, so if your writes are the bottleneck, more replicas won’t help at all.
- Picture an app where people are constantly writing, like a system swallowing millions of sensor readings a second. That primary gets buried by writes, and replicas can’t take any of that off its plate.
- When writes become the problem, you need to split the data itself across multiple machines so writes spread out too. That technique is called sharding.
So the rule of thumb is simple. Reads are your bottleneck, reach for read replicas. Writes are your bottleneck, you’re looking at sharding. We link to both topics at the end so you can go deeper.
⚠️ Common Mistakes and Misconceptions
A few ideas trip people up with read replicas. Let’s clear them out:
- “Read replicas scale writes.” No. They scale reads only. Every write still lands on the one primary, so replicas do nothing for write load.
- “Reads from a replica are always current.” Not guaranteed. Replication lag means a replica can be slightly behind, so you may get a stale read just after a write.
- “I can send writes to a replica.” You can’t. Replicas are read-only. Writes must go to the primary, period. Sending a write to a replica will just fail.
- “More replicas always means a faster app.” Only if reads are your bottleneck. If writes are the problem, piling on replicas doesn’t help, and it can even add lag since the primary has more copies to feed.
🛠️ Design Challenge
Try this one on your own to test yourself.
You’re designing the backend for a blogging site. Millions of people read articles, but only a few thousand writers actually publish. Now think through:
- Where do you send a request to publish a new article? Primary or replica?
- Where do you send the millions of requests to read articles?
- A writer hits publish and then immediately views their post. How do you make sure they see it and don’t think it failed?
- Reads are exploding but writes are tiny. Do you add more replicas, or do you shard? Why?
Walk through each answer out loud. If you can reason about where reads and writes go and how to dodge stale reads, you’ve got the core of this topic.
🧩 What You’ve Learned
You can now explain how read replicas help an app scale. Here’s what you’ve picked up.
- ✅ A read replica is a read-only copy of your primary database that serves read queries.
- ✅ Writes go to the primary, which copies changes out to the replicas; reads get spread across the replicas.
- ✅ Replicas offload reads from the primary, scale read-heavy apps, and double as a standby backup.
- ✅ Replication lag can cause stale reads, which leads to the “read your own writes” problem.
- ✅ You handle that by reading from the primary right after a write.
- ✅ Replicas don’t scale writes; when writes are the bottleneck, you shard instead.
Check Your Knowledge
Test what you learned. Pick an answer for each question, then click Check.
- 1
What is a read replica?
Why: A read replica holds a copy of the primary's data and answers reads only; it never accepts writes.
- 2
Do read replicas help scale writes?
Why: All writes go to the one primary, so adding replicas raises read capacity but not write capacity.
- 3
What is replication lag?
Why: During this gap a replica is slightly behind the primary, which can cause a stale read.
- 4
How do you handle the 'read your own writes' problem?
Why: Reading from the primary just after a write ensures the user always sees their own recent change.
🚀 What’s Next?
Read replicas are one piece of scaling a database. Next, go deeper into how the copying actually works and what to do when writes are your problem.
- Database Replication explains how data gets copied from the primary to the replicas, and the different ways to keep them in sync.
- Database Sharding shows how to split your data across machines so you can scale writes too, not just reads.