databasecachingcost-optimizationarchitecture

Read replica or cache: which one actually costs less per read

A read replica is a full copy of your database with a full copy of its price. A cache node is a fraction of that. The choice comes down to hit ratio, data freshness, and how many distinct queries you are serving. Here is the cost-per-read math.

The C3X Team··7 min read

Quick answer

A read replica costs the same as the primary: a db.r6g.xlarge PostgreSQL replica in us-east-1 runs about $0.518 per hour, roughly $378 per month, plus a full copy of storage at $0.115 per GB-month. A cache.r6g.large ElastiCache node with 13 GB of memory costs about $0.206 per hour, roughly $150 per month and can absorb far more reads per dollar when the hit ratio is high. Rule of thumb: if your read traffic concentrates on a small hot set and can tolerate seconds of staleness, cache first, because an 85 percent hit ratio removes 85 percent of reads for 40 percent of a replica's price. If reads are diverse, ad hoc, or must be transactionally fresh, a replica is the honest answer.

When a primary database starts running hot on reads, two answers present themselves: add a read replica, or put a cache in front. Teams often pick by familiarity rather than by arithmetic, which is a shame, because the cost difference per read served can be an order of magnitude in either direction depending on the access pattern.

The list prices

ResourceSpecus-east-1 on-demandMonthly
RDS PostgreSQL db.r6g.large2 vCPU, 16 GB$0.259/hrabout $189
RDS PostgreSQL db.r6g.xlarge4 vCPU, 32 GB$0.518/hrabout $378
ElastiCache cache.r6g.large2 vCPU, 13.07 GB$0.206/hrabout $150
ElastiCache cache.r6g.xlarge4 vCPU, 26.32 GB$0.411/hrabout $300
ElastiCache cache.t4g.medium2 vCPU, 3.09 GB$0.068/hrabout $50
RDS gp3 storageper GB$0.115/GB-mo500 GB = $57.50

The critical asymmetry: a read replica carries a full second copy of storage. A 500 GB database replicated once costs $378 for compute plus $57.50 for storage, about $435 per month. The cache carries no storage charge at all, because it holds a working set in memory and forgets the rest.

Cost per read served

Take a workload doing 4,000 reads per second at peak, roughly 10.4 billion reads per month if sustained. A db.r6g.xlarge replica handling that load costs $435 per month, about $0.042 per million reads. A cache.r6g.large easily sustains well over 100,000 operations per second on a single node, so the same 10.4 billion reads through cache cost $150 per month, about $0.014 per million reads, roughly a third of the replica's rate.

But the cache only serves the reads it hits. At an 85 percent hit ratio the remaining 15 percent, about 1.56 billion reads, still land on the primary. If the primary was already sized for writes plus that residual read load, you have avoided the replica entirely and your total incremental cost is $150 instead of $435, a saving of about $285 per month. At a 40 percent hit ratio the residual 60 percent probably still needs the replica, and now you are paying for both: $585 per month for an architecture that a replica alone would have served for $435.

The break-even hit ratio

A simple way to frame it: caching wins when the hit ratio is high enough that the residual read load fits inside the primary's existing headroom. If the primary is at 70 percent CPU with reads contributing 50 points of that, a cache that removes 85 percent of reads takes reads down to roughly 7.5 points, leaving the primary at about 27 percent. That is comfortable. A cache removing 40 percent leaves reads at 30 points, primary at 50 percent, which is survivable but leaves no failover headroom.

Hit ratio is mostly a function of key cardinality and request skew. Session lookups, product catalogs, feature flags, permission checks, and rendered fragments cache beautifully because a small hot set absorbs most traffic. Reporting queries, filtered searches with many parameter combinations, and per-user timelines cache badly because every request is a distinct key. Measure the skew before you buy either option: pull a day of query logs, hash the normalized query plus bound parameters, and count what fraction of requests fall in the top 1,000 keys.

The hidden costs on each side

OptionHidden cost
Read replicaSecond storage copy, cross-AZ replication traffic, backup scope, version upgrades doubled
CacheInvalidation logic, stale-read bugs, warm-up after node replacement, a second failure domain

A cross-AZ read replica also pays data-transfer charges on replication traffic at $0.01 per GB in each direction. A write-heavy database generating 200 GB of WAL per day sends about 6 TB per month to the replica, which at $0.02 per GB round trip is roughly $120 per month of pure transfer. That is a line people forget entirely, and it can be a quarter of the replica's compute cost.

On the cache side, the real expense is engineering time on invalidation. A cache with a 60 second TTL and no explicit invalidation is cheap to build and produces a support ticket every time someone updates a record and does not see the change. A correctly invalidated cache is more code, more tests, and more ways to be subtly wrong.

The practical recommendation

Start with a cache when reads are skewed and staleness of a few seconds is acceptable, because it is the cheaper instrument per read removed and it does not double your storage bill. Add a replica when reads are diverse, when analytical queries need to be isolated from transactional ones, or when you need a second copy for availability reasons anyway. Many mature systems run both, and that is fine as long as the cache is earning its hit ratio.

Whichever you choose, price it from Terraform before you merge so the second storage copy and the cross-AZ replication traffic appear in the estimate rather than on the invoice. Compare node families and replica configurations against the resource catalog, and see read replica cost against performance for the replica-side detail.

FAQ

Is a cache cheaper than a read replica?

Per read served, usually yes. A cache.r6g.large at about $150 per month sustains well over 100,000 operations per second, roughly $0.014 per million reads, versus about $0.042 per million for a db.r6g.xlarge replica at $435 per month including its storage copy. But the cache only serves reads it hits, so a low hit ratio means you pay for both the cache and the replica you still needed.

What hit ratio makes caching worth it?

Caching wins when the residual read load fits inside the primary's existing headroom. If reads contribute 50 points of CPU, an 85 percent hit ratio reduces that to about 7.5 points and you avoid the replica entirely. A 40 percent hit ratio leaves 30 points, which usually still requires the replica, so you end up paying for both. Measure request skew from query logs before committing.

Do read replicas cost the same as the primary?

Yes for compute, and they add a full second copy of storage. A db.r6g.xlarge replica is $0.518 per hour, about $378 per month, plus 500 GB of gp3 storage at $0.115 per GB-month, about $57.50, for roughly $435 total. Caches carry no storage charge because they hold only a working set in memory.

What is the hidden cost of a cross-AZ read replica?

Replication data transfer at $0.01 per GB in each direction. A database generating 200 GB of WAL per day sends about 6 TB per month to a cross-AZ replica, which at $0.02 per GB round trip is roughly $120 per month of pure transfer, about a quarter of the replica's compute cost. It is a line item that rarely appears in planning estimates.

Which workloads cache well?

Session lookups, product catalogs, feature flags, permission checks, and rendered page fragments cache well because a small hot set absorbs most traffic. Reporting queries, filtered searches with many parameter combinations, and per-user timelines cache badly because nearly every request is a distinct key. Hash normalized queries plus bound parameters over a day of logs and check what share falls in the top 1,000 keys.

How does C3X help decide between a replica and a cache?

C3X prices both options from Terraform before you merge, including the pieces that are easy to forget: the replica's second storage copy and its cross-AZ replication transfer, or the cache node family and size. Seeing both architectures costed in the pull request turns a familiarity-driven choice into an arithmetic one, and catches the case where you are paying for a cache and a replica that does the same work.

What to do next

Cost both read-scaling options before you pick one. C3X reads your Terraform and prices your resources against a live catalog. Start with the quickstart.

Try C3X on your own Terraform

Free and open source. No API key required. One command to install, one command to estimate.