Prompt
PostgreSQL read replicas for application
Latest observation
PostgreSQL read replicas are a common way to scale read-heavy applications and improve availability. Here’s a practical overview for using them with an application.
What they are
A read replica is a PostgreSQL instance that continuously receives changes from the primary database via streaming replication.
- Primary: handles writes
- Replica(s): handle read-only queries
When to use them
Use read replicas if:
- Your app has a lot of
SELECTtraffic - You want to offload reporting or analytics queries
- You need better read latency in another region
- You want a standby for failover
Important limitation
Read replicas are usually eventually consistent:
- A write to the primary may not be visible on a replica immediately
- So after
INSERT/UPDATE/DELETE, reading from a replica may return stale data
This is the biggest thing application design must account for.
Common application patterns
1. Split reads and writes
Route:
SELECTqueries → replicasINSERT/UPDATE/DELETE→ primary
This is the standard approach.
2. Read-after-write consistency
If a user writes data and then immediately reads it, ensure that read goes to:
- the primary, or
- a replica only after replication lag is acceptable
Common tactics:
- “stick” a user/session to the primary for a short time after a write
- use the primary for requests in the same transaction flow
- add a small “consistency window” before allowing replica reads
3. Replica-aware query routing
Use:
- application-side routing logic
- a database proxy/load balancer
- ORM support if available
Examples:
- custom read/write splitting in the app
- Pgpool-II, HAProxy, Odyssey, or cloud provider proxies
- framework features in Django, Rails, Laravel, etc.
Things to watch out for
Replication lag
Replicas may be behind the primary. Your app should:
- monitor lag
- avoid using replicas for strongly consistent reads
- fall back to primary if lag is too high
Long-running queries
Heavy reporting queries on replicas can cause:
- stale reads
- replica slowdown
- delayed replication apply
Transactions
A replica cannot accept writes, so:
- don’t send transactions requiring writes to replicas
- avoid using replicas for workflows needing strict serial consistency
Failover
If the primary fails:
- one replica is promoted
- your app must reconnect to the new primary
- connection pooling and DNS/proxy strategy matter
Recommended architecture
A practical setup is:
- Primary DB for writes and critical reads
- One or more replicas for general read scaling
- Proxy/router to direct traffic
- Monitoring for replication lag and health
- Fallback to primary when replicas are lagging or unavailable
Application design tips
- Keep read/write separation explicit
- Identify queries that require fresh data
- Use replicas for:
- dashboards
- feeds
- product catalogs
- search result enrichment
- Use primary for:
- checkout/payment flows
- user profile updates immediately after change
- permissions/authentication-sensitive reads
If you want a simple rule
A good default is:
Route all writes to the primary, route most reads to replicas, and route any read that must see the latest write to the primary.
If you want, I can also give you:
- a sample architecture diagram,
- PostgreSQL replica setup steps, or
- application code examples for routing reads/writes.