Smart read replica for PostgreSQL

Read replicas copy everything.
This one doesn't.

A wire-compatible PostgreSQL proxy that replicates only the working set your traffic touches. One connection string, no invalidation code, and you stop paying for rows nobody reads.

PostgreSQL 16, 17 & 18 · Deployed on AWS · 30-day free trial

docker run -d -p 5432:5432 -p 9090:9090 \
  pgcache/pgcache \
  --upstream postgres://user@db:5432/myapp

# 5432  Postgres wire protocol: point your app here
# 9090  Prometheus metrics and /healthz
#
# Origin needs wal_level = logical

Independently benchmarked

PgCache 0.6.2 on PostgreSQL 17, against a synthetic e-commerce schema of 16 million rows. 150 runs per query at concurrency 10.

Point lookup by id

0.3 ms 0.3 ms

Count by tier, 1M rows

140 ms 0.5 ms

Revenue by country, 5M-row join

1.4 s 0.5 ms

Top products, 10M-row join

2.9 s 0.6 ms

Measured by Hulunlante Worku, who does not work for us and was not paid. Benchmarks →

Read replicas weren’t built for read offloading

Scaling reads shouldn’t mean paying to copy your entire database.

You pay to replicate cold data

Most traffic hits ~20% of your data. A traditional read replica still copies 100% of it. You pay storage, compute, and IO on rows nobody reads.

Read replicas are all-or-nothing

You can’t replicate just the hot tables. Scaling reads means another full copy of a database that only keeps growing.

Aurora IO billing punishes read scaling

Every replica read is billable IO, and IO-Optimized runs ~33% more. The more you offload reads, the more the replica costs.

Bolting on a cache means rewriting your app

A Redis layer adds invalidation logic, a new system to run, and stale-data bugs: work the database team didn’t want to own.

How we stack up

The same read offloading as a replica, without copying your whole database or running a cache layer.

Traditional read replica Redis cache layer PgCache
Data copied 100% of the database Whatever you hand-code Only the hot working set
Freshness Replication lag Manual invalidation & TTLs Replication lag
App code changes Route reads to replica Cache + invalidation logic One connection string
New system to run Another full database Redis to scale & secure A drop-in proxy
Cost model Storage + compute + IO on everything Redis infra + engineering time Predictable hourly rate, no monthly fee

A read replica, minus the waste

The read offloading you want from a replica, without copying your entire database.

Copies only the hot data

PgCache replicates the working set your traffic actually touches, not the whole database. Fractional storage, fractional cost.

Freshness backed by PostgreSQL Logical Replication

PgCache tracks changes via logical replication and routes anything it can’t safely serve straight to your origin. Cache speed, without stale reads.

Drop-in, no code changes

A wire-compatible Postgres proxy. Change one connection string. No Redis layer, no ORM changes, no schema migration.

Predictable monthly cost

Billed hourly on AWS Marketplace. Run it 24/7 like a read replica and it’s a flat, forecastable line item. No per-query charges, no monthly software fee.

From full replica to fractional in three steps

No migration, no app rewrite, no Redis.

1

Launch PgCache

Deploy from the AWS Marketplace AMI, Docker, or bare metal, and point it at your origin database.

# AWS Marketplace AMI, or:
docker run -d -p 5432:5432 pgcache/pgcache \
  --upstream postgres://user@db:5432/myapp
2

Change one connection string

Send reads through PgCache. Writes still go straight to your primary, unchanged.

# Before
DATABASE_URL=postgres://user@replica:5432/myapp

# After
DATABASE_URL=postgres://user@pgcache:5432/myapp
3

Offload reads automatically

PgCache caches the hot working set and keeps it fresh with logical replication. Cold data never gets copied.

# Your existing code works unchanged
users = db.query("SELECT * FROM users WHERE active = true")
Your App
PgCache
PostgreSQL

PgCache sits between your application and PostgreSQL, transparently caching queries.

Estimate your savings

See what you stop paying when you offload reads to PgCache instead of running a full replica.

$4,128 estimated savings / year

Swap a $500/mo replica for m6g.large at $156/mo all-in, about $344/mo saved.

PgCache copies only the hot working set, not your whole database.

Try free on AWS Marketplace

All-in estimate: PgCache hourly rate + EC2 on-demand (us-east-1, Linux), ~730 hrs/mo. Excludes EBS storage. Rough estimate for discussion; actual savings depend on your workload.

Built for the people who own the database bill

From the DBA who signs off on replicas to the developer who just wants fast reads.

DBAs & Database Engineers

Cut replica cost

Offload read traffic without provisioning another full copy of a growing database. Stop paying compute and IO on cold data.

SREs

Add read capacity without a project

Drop PgCache onto a cluster: no schema migration, no app changes, and no internal fight to get a read replica approved.

Platform & Infra Engineers

Make infra spend predictable

Replace fractional-value read replicas with usage-based cost you can actually forecast and budget.

Backend Developers

Faster reads, zero cache code

Hot queries return in milliseconds with no invalidation logic to write, test, or debug. Your ORM doesn’t change.

Will PgCache work for you?

The fastest way to know if PgCache fits. If you see your blocker here, you save a sales call.

Shipping soon

Read-after-write consistency

Inside a transaction every query goes to your origin, so you always see your own writes. Outside one, typical replication lag applies; a stronger guarantee is in active development.

Not yet supported

Row-Level Security (RLS)

If your reads depend on Postgres RLS policies, PgCache isn't the right fit today. If you don't use RLS, this doesn't affect you.

Mostly transparent

Schema changes

Most schema changes are worry-free. The exception: dropping a table, or attaching or detaching a partition that already holds rows, can serve stale results.

Passes through

Time-based & volatile queries

Queries using now(), CURRENT_DATE, random() and similar non-immutable functions aren't cached. They go straight to your origin every time: correct, just not accelerated.

Supported on PostgreSQL 16, 17, and 18. Works with any ORM or driver that speaks the Postgres wire protocol.

Design Partner

“I’m extremely excited about PgCache. I think in the future it will become a standard tool in a backend stack for Postgres.”
Leonardo Benedet DBA, ContaAzul

Stop paying to replicate cold data

Launch a free instance on AWS Marketplace and watch your cache hit rate climb in minutes.

Try free on AWS Marketplace 30-day free trial · live in minutes

or stay in touch

No spam. Unsubscribe anytime.

Looking for hands-on onboarding? Join our pilot program.