PostgreSQL Replication and High Availability
PostgreSQL provides robust data replication and high availability (HA) capabilities, allowing organizations to build resilient architectures that guarantee data durability and minimal downtime. Replication in PostgreSQL is categorized into physical replication (WAL-based byte-level streaming) and logical replication (table-level change publishing). These mechanisms can be deployed individually or combined to meet diverse business requirements. This article explores the configuration of streaming replication, the implementation of logical replication, and production-grade automated failover strategies.
Physical Replication
- Operates at the block level by copying Write-Ahead Log (WAL) segments.
- Supports both synchronous and asynchronous operational modes.
- Replicates an entire database cluster, making it ideal for disaster recovery and read-scale architectures.
Logical Replication
- Employs a publish-and-subscribe model targeting specific tables or schemas.
- Offers granular control, enabling data synchronization across different major versions or distinct architectures.
- Frequently utilized for data migrations, data sharding, and real-time analytics feeds.
Streaming Replication Configuration
The following guide demonstrates setting up synchronous streaming replication between two nodes, designated as master and standby, using PostgreSQL 15.
1. Prerequisites
# Install identical PostgreSQL versions on both hosts
apt-get install postgresql-15
# Ensure time synchronization between nodes via NTP
timedatectl set-ntp true
2. Master Node Configuration
Modify postgresql.conf (typically located at /etc/postgresql/15/main/postgresql.conf):
# Listen on all network interfaces (restrict to internal subnets in production)
listen_addresses = '*'
# Enable WAL configuration for replication
wal_level = replica
max_wal_senders = 10
wal_keep_size = 1024 # Measured in MB to prevent premature WAL recycling
archive_mode = on
archive_command = 'test ! -f /var/lib/postgresql/wal_archive/%f && cp %p /var/lib/postgresql/wal_archive/%f'
Update pg_hba.conf to grant connection permissions to the standby node:
# TYPE DATABASE USER ADDRESS METHOD
host replication replicator 192.168.10.0/24 md5
Create a dedicated replication role in the database:
CREATE ROLE replicator WITH REPLICATION LOGIN PASSWORD 'StrongPass123';
Restart the master service to apply changes:
systemctl restart postgresql
3. Base Backup Execution
Execute pg_basebackup on the standby host to clone the master's data directory:
pg_basebackup -h 192.168.10.1 -D /var/lib/postgresql/15/main -U replicator -P --wal-method=stream
Upon completion, a standby.signal file is automatically generated in the data directory, designating the instance as a warm or hot standby.
4. Standby Node Configuration
Configure postgresql.conf on the standby instance:
primary_conninfo = 'host=192.168.10.1 port=5432 user=replicator password=StrongPass123 application_name=standby1'
primary_slot_name = 'standby1_slot' # Optional, utilizes a replication slot to avoid WAL loss
If utilizing a replication slot, create it on the master node first:
SELECT * FROM pg_create_physical_replication_slot('standby1_slot');
Start the standby service:
systemctl start postgresql
Running SELECT pg_is_in_recovery(); on the standby should now return true, confirming it is operating in recovery mode.
5. Verifying Replication Status
Execute the following query on the master node:
SELECT client_addr, state, sync_state FROM pg_stat_replication;
- A
stateofstreamingindicates active log shipping. - A
sync_stateofsyncconfirms synchronous operation (whensynchronous_standby_namesis configured).
Implementing Synchronous Replication
PostgreSQL defaults to asynchronous replication, where transaction commits return immediately without waiting for standby acknowledgment. To enforce synchronous replication, specify the standby identifier in postgresql.conf:
synchronous_standby_names = 'standby1'
While synchronous replication introduces minor transaction latency overhead, it guarantees zero data loss upon master failure.
Logical Replication Example
To stream a single table, such as public.sales, to a reporting replica:
1. Master Publication Setup
-- Set WAL level to logical
ALTER SYSTEM SET wal_level = logical;
SELECT pg_reload_conf();
-- Create a publication for the target table
CREATE PUBLICATION sales_pub FOR TABLE public.sales;
2. Standby Subscription Configuration
Establish the subscription on the target database instance:
CREATE SUBSCRIPTION sales_sub
CONNECTION 'host=192.168.10.1 port=5432 dbname=shop user=replicator password=StrongPass123'
PUBLICATION sales_pub;
The database engine automatically copies existing data and continuously replicates subsequent INSERT, UPDATE, and DELETE operations.
High Availability Architecture Overview
| Architecture | Core Components | Best Suited For | Primary Advantages | Primary Drawbacks |
|---|---|---|---|---|
| Patroni + Etcd/Consul | Patroni (Failover Daemon), Etcd/Consul (Distributed Store) | Enterprise systems requiring automated failover | Fully automated, supports sync/async switching, scalable | Requires external coordination services |
| PgBouncer + HAProxy | PgBouncer (Pooling), HAProxy (Load Balancing) | Read-scale distributions, traffic routing | Lightweight, decouples read traffic | Failover requires external orchestration |
| repmgr | repmgr (Replication Manager CLI) | Mid-sized clusters prioritizing native tooling | Straightforward configuration, includes monitoring utilities | Lower automation level than Patroni |
| Citus | Citus (Distributed Extension) | Large-scale analytics, horizontal scaling | Automatic sharding, parallelized queries | Specialized extension dependency, higher infrastructure overhead |
Patroni Workflow Mechanics
- Health Probing: Each PostgreSQL instance runs a Patroni agent that periodically evaluates local node health and replication lag.
- Distributed Locking: Using Etcd, Consul, or ZooKeeper, Patroni maintains a distributed leader key to ensure only one primary accepts writes at any time.
- Failure Detection: If the primary drops its lock renewal or fails health checks, standby agents contend to acquire the leadership lease.
- Promotion: The newly elected node promotes itself via
pg_ctl promote, updates the metadata store, and directs proxy layers like HAProxy to reroute write traffic.
Minimal Deployment Example (Docker Compose)
version: '3.7'
services:
etcd:
image: bitnami/etcd:latest
environment:
- ALLOW_NONE_AUTHENTICATION=yes
ports: ["2379:2379"]
patroni0:
image: patroni:latest
environment:
- PATRONI_NAME=node0
- PATRONI_SCOPE=pgcluster
- PATRONI_ETCD_HOSTS=etcd:2379
- PATRONI_REPLICATION_USERNAME=replicator
- PATRONI_REPLICATION_PASSWORD=StrongPass123
depends_on: [etcd]
patroni1:
image: patroni:latest
environment:
- PATRONI_NAME=node1
- PATRONI_SCOPE=pgcluster
- PATRONI_ETCD_HOSTS=etcd:2379
- PATRONI_REPLICATION_USERNAME=replicator
- PATRONI_REPLICATION_PASSWORD=StrongPass123
depends_on: [etcd]
Troubleshooting and Tuning Best Practices
Exhaustion of Disk Space Caused by WAL Growth
- Tune
wal_keep_sizeandmax_wal_size, and activatearchive_commandto offload segments to durable external storage. - Leverage analysis utilities like
pgBadgerto inspect workload patterns.
- Tune
Replication Lag
- Monitor network bandwidth and storage subsystem throughput.
- Enable
hot_standby_feedback = onon standby servers to prevent long-running read queries from causing vacuum conflicts on the primary.
Logical Replication Conflicts
- Address concurrent conflicting mutations by configuring conflict resolution rules or applying row filters on publications.
False Positive Failover Triggers
- Adjust lease
ttlandretry_timeoutparameters in distributed configuration stores to prevent transient network partitions from forcing unnecessary failovers.
- Adjust lease
Summary
PostgreSQL offers a mature and production-ready framework for replication and high availability. Successful implementations depend on selecting the correct replication paradigm, defining clear consistency models, integrating automated failover orchestration, and maintaining proactive telemetry. Mastering these concepts ensures reliable, scalable database services capable of sustaining mission-critical workloads.