Prompt

How do I set up read replicas in PostgreSQL for a production app?

Technology / Databases1 observationLast seen Oct 7, 2026

Latest observation

Oct 7, 2026OpenAI APIWeb search: off

Setting up PostgreSQL read replicas for a production app usually means creating one primary (read/write) server and one or more standby servers that continuously replay WAL changes from the primary. For production, the main goals are:

  • protect the primary from heavy read traffic
  • improve read scalability
  • provide disaster recovery / failover options
  • minimize replication lag and operational risk

Here’s a practical production-oriented approach.


1) Choose the replication model

PostgreSQL supports two common patterns:

Physical replication

  • Copies the entire data cluster at the block/WAL level.
  • Most common for read replicas.
  • Simple and fast.
  • Replica is usually read-only.

Logical replication

  • Replicates selected tables or changes.
  • Useful for partial replication, migrations, cross-version scenarios.
  • More flexible, but more operational overhead.

For most production read-replica setups, physical streaming replication is the right choice.


2) Basic architecture

Typical setup:

  • Primary
    • accepts writes
    • streams WAL to replicas
  • Read replicas
    • receive WAL
    • replay changes
    • serve read-only queries
  • Optional:
    • load balancer / router for read traffic
    • monitoring for lag and health
    • failover manager for automatic promotion

3) Configure the primary

You need to enable replication-related settings in postgresql.conf or your managed service settings.

Common parameters:

wal_level = replica
max_wal_senders = 10
max_replication_slots = 10
hot_standby = on
wal_keep_size = 1GB

Notes:

  • wal_level = replica is required for streaming replication.
  • max_wal_senders controls concurrent replica connections.
  • wal_keep_size helps prevent replicas from falling too far behind.
  • hot_standby is for replicas, but setting is common in cluster configs.
  • If you use replication slots, you may not need a large wal_keep_size, but you must monitor disk usage carefully.

Allow replica connections

In pg_hba.conf, allow the replica host to connect:

host replication repl_user 10.0.0.0/24 scram-sha-256

Then create a replication user:

CREATE ROLE repl_user WITH REPLICATION LOGIN PASSWORD 'strong-password';

Reload PostgreSQL after changes:

SELECT pg_reload_conf();

or restart if needed.


4) Take a base backup for the replica

A replica needs an initial copy of the primary data directory.

Use pg_basebackup:

pg_basebackup \
  -h primary-db.example.com \
  -U repl_user \
  -D /var/lib/postgresql/data \
  -Fp -Xs -P -R

What these mean:

  • -h: primary host
  • -U: replication user
  • -D: target data directory
  • -Fp: plain format
  • -Xs: stream WAL during backup
  • -P: progress
  • -R: write replica connection info automatically

If you’re managing it manually, you can also configure standby connection settings yourself.


5) Start the replica

On the standby server:

  • ensure PostgreSQL version matches the primary
  • make sure the data directory is initialized from the base backup
  • start PostgreSQL

The replica should connect to the primary and begin streaming WAL.

Check status:

SELECT * FROM pg_stat_wal_receiver;

On the primary, check connected replicas:

SELECT * FROM pg_stat_replication;

6) Make sure reads go to replicas only

Your application must route traffic carefully.

Common patterns

A. Separate read and write connection pools

  • writes -> primary
  • reads -> replicas
  • easiest and most common in application code

B. Use a database proxy/router

Examples:

  • PgBouncer
  • HAProxy
  • AWS RDS Proxy
  • custom service discovery / DNS

Note: PgBouncer is great for pooling, but it does not automatically route reads vs writes by itself. You usually still need app logic or a router.

C. ORM-level read/write splitting

Some frameworks support this directly:

  • Django database routers
  • Rails multiple databases
  • Hibernate read/write routing
  • Sequelize/TypeORM patterns, depending on usage

7) Handle replication lag correctly

Replicas are usually asynchronous by default, which means:

  • writes commit on primary first
  • replicas catch up shortly after
  • reads from replicas may briefly be stale

This matters for:

  • user just changed profile, then immediately refreshes page
  • checkout / payments / critical workflows
  • any “read your own writes” requirement

Common solutions

  • read from primary immediately after a write
  • add a short “stickiness” window to the primary
  • use synchronous replication for critical data, selectively if needed
  • display slightly stale data only where acceptable

You can monitor lag with:

SELECT
  pid,
  application_name,
  state,
  sync_state,
  write_lag,
  flush_lag,
  replay_lag
FROM pg_stat_replication;

And on replica:

SELECT now() - pg_last_xact_replay_timestamp() AS replay_delay;

8) Use replication slots carefully

Replication slots prevent WAL segments from being removed before a replica consumes them.

This is useful because:

  • replicas won’t miss required WAL
  • easier to avoid broken replication after brief outages

But the risk is:

  • if a replica dies or lags forever, WAL can pile up and fill disk

Create a slot:

SELECT pg_create_physical_replication_slot('replica1');

Use it in the standby configuration.

For production, replication slots are often a good idea, but you must actively monitor them.


9) Plan for failover

Read replicas are not the same as automatic high availability unless you design for it.

If the primary fails, you may need to:

  • promote a replica
  • redirect application writes
  • rebuild old primary as a replica later

Manual promotion

On the replica:

pg_ctl promote -D /var/lib/postgresql/data

Or:

SELECT pg_promote();

Automated failover tools

Consider:

  • Patroni
  • repmgr
  • Pacemaker/Corosync
  • cloud-managed HA features

For production, automatic failover is strongly recommended if downtime matters.


10) Monitor the setup

At minimum, monitor:

  • replica lag
  • WAL sender/receiver health
  • disk space on primary and replicas
  • replication slot backlog
  • query latency on replicas
  • connection counts
  • failover state

Useful views:

  • pg_stat_replication
  • pg_stat_wal_receiver
  • pg_replication_slots

11) Production best practices

Use at least one replica in another failure domain

If possible:

  • different AZ
  • different rack
  • different machine / subnet

Keep versions consistent

  • same PostgreSQL major version for physical replication
  • replicas should usually match the primary closely

Test failover regularly

Don’t assume it works until you’ve rehearsed:

  • promotion
  • DNS or load balancer switch
  • app reconnect behavior
  • recovery of old primary

Don’t put everything on replicas

Avoid using replicas for:

  • critical transactional reads that must be fully fresh
  • advisory locks
  • session state
  • any workload sensitive to staleness

Be careful with long-running queries

Replica replay can be delayed by heavy queries, and hot standby conflicts may cancel queries depending on settings.


12) Example simple production checklist

  1. Enable WAL streaming on primary
  2. Create replication user
  3. Allow replica IPs in pg_hba.conf
  4. Initialize replica with pg_basebackup
  5. Start replica and verify streaming
  6. Route reads only to replicas
  7. Monitor lag and disk usage
  8. Set up failover tooling
  9. Test promotion and recovery
  10. Document your runbook

13) If you’re using a managed service

If you’re on:

  • AWS RDS / Aurora
  • Google Cloud SQL
  • Azure Database for PostgreSQL
  • DigitalOcean Managed PostgreSQL

then replicas are often provisioned through the provider console/CLI, and many replication details are managed for you. You still need to handle:

  • read/write routing
  • lag awareness
  • failover behavior
  • app reconnection logic

14) Quick recommended approach for most production apps

If you want a safe default:

  • use physical streaming replicas
  • use one or more replicas in separate AZs
  • route read-heavy, non-critical reads to replicas
  • keep write-after-read-sensitive flows on the primary
  • use monitoring + failover automation like Patroni/repmgr or your managed provider’s HA
  • add replication slots only if you can monitor them properly

If you want, I can give you:

  1. a step-by-step setup guide on Linux with exact config files,
  2. a Docker Compose demo, or
  3. a cloud-specific guide for AWS RDS, GCP Cloud SQL, or Azure.

Observation history

How did Obsurfable measure this prompt?

Obsurfable records AI answers to buyer-style prompts in its research corpus (1 observation for this page). Metrics are distributions over observations, not a single static ranking.

Which AI systems does Obsurfable collect answers from?

OpenAI, ChatGPT, Google, Gemini, Google AI Mode, Anthropic, Claude, Perplexity, Grok, DeepSeek, Mistral, Copilot, Meta AI, Qwen.

How can brands improve their AEO?

Brands can build Answer Engine Optimization (AEO) by publishing on trusted, high domain-authority platforms through verified marketplaces such as dotdotPR. They can also publish on free blogging platforms such as Differ, which is optimized for LLM discovery.

Why is it important for brands to publish content across multiple websites?

Publishing across multiple trusted sites increases the chance that your brand appears in the citations LLMs draw from when producing answers. Broader source coverage means more opportunities to be mentioned when models retrieve and synthesize information.

Want this interpreted for your brand?

Explorer is the free public corpus. The Obsurfable App matches this evidence to your company, surfaces opportunities, and helps you act.