Configure PostgreSQL 17 streaming replication for high availability with automatic failover

Advanced 45 min Apr 08, 2026 286 views
Ubuntu 24.04 Debian 12 AlmaLinux 9 Rocky Linux 9

Set up PostgreSQL 17 streaming replication between primary and replica servers with pg_auto_failover for automated high availability. This tutorial covers complete configuration from authentication to monitoring and maintenance procedures.

Prerequisites

  • At least 3 servers (primary, replica, monitor)
  • Minimum 4GB RAM per server
  • Network connectivity between servers
  • Basic PostgreSQL administration knowledge
  • Root or sudo access on all servers

What this solves

PostgreSQL streaming replication creates real-time copies of your database on multiple servers, providing high availability and disaster recovery. When combined with pg_auto_failover, your system automatically promotes replica servers to primary when failures occur, minimizing downtime and data loss.

Step-by-step configuration

Update system packages

Start by updating your package manager to ensure you get the latest PostgreSQL packages.

sudo apt update && sudo apt upgrade -y
sudo apt install -y wget ca-certificates
sudo dnf update -y
sudo dnf install -y wget ca-certificates

Install PostgreSQL 17 repository

Add the official PostgreSQL repository to get the latest version with streaming replication features.

sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
sudo apt update
sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-9-x86_64/pgdg-redhat-repo-latest.noarch.rpm

Install PostgreSQL 17 and pg_auto_failover

Install PostgreSQL server, client tools, and the pg_auto_failover extension for automated failover management.

sudo apt install -y postgresql-17 postgresql-client-17 postgresql-17-auto-failover
sudo systemctl enable postgresql
sudo systemctl start postgresql
sudo dnf install -y postgresql17-server postgresql17 postgresql17-auto-failover
sudo /usr/pgsql-17/bin/postgresql-17-setup initdb
sudo systemctl enable postgresql-17
sudo systemctl start postgresql-17

Create replication user on primary server

Create a dedicated user for replication with the necessary privileges for streaming and monitoring.

sudo -u postgres createuser --replication --login replica_user
sudo -u postgres psql -c "ALTER USER replica_user PASSWORD 'SecureRepPass2024!';"

Configure primary server postgresql.conf

Enable WAL archiving, set replication parameters, and configure connection settings for streaming replication.

# Connection settings
listen_addresses = '*'
port = 5432
max_connections = 200

Replication settings

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

Archive settings

archive_mode = on archive_command = 'test ! -f /var/lib/postgresql/17/main/archive/%f && cp %p /var/lib/postgresql/17/main/archive/%f'

Logging

log_replication_commands = on log_line_prefix = '%t [%p]: [%l-1] user=%u,db=%d,app=%a,client=%h '

Performance

shared_buffers = 256MB wal_buffers = 16MB checkpoint_completion_target = 0.9

Configure primary server pg_hba.conf

Allow replication connections from replica servers with MD5 authentication for security.

# Allow local connections
local   all             postgres                                peer
local   all             all                                     md5

Allow host connections

host all all 127.0.0.1/32 md5 host all all ::1/128 md5

Allow replication connections

host replication replica_user 203.0.113.20/32 md5 host replication replica_user 203.0.113.21/32 md5

Allow application connections

host all all 203.0.113.0/24 md5

Create archive directory and restart primary

Create the WAL archive directory with correct permissions and restart PostgreSQL to apply configuration changes.

sudo mkdir -p /var/lib/postgresql/17/main/archive
sudo chown postgres:postgres /var/lib/postgresql/17/main/archive
sudo chmod 750 /var/lib/postgresql/17/main/archive
sudo systemctl restart postgresql
Note: Never use chmod 777 for database directories. The correct permissions (750) allow only the postgres user and group access while preventing unauthorized access from other system users.

Take base backup for replica server

Create a base backup of the primary database to initialize the replica server with current data.

sudo systemctl stop postgresql
sudo rm -rf /var/lib/postgresql/17/main/*
sudo -u postgres pg_basebackup -h 203.0.113.10 -D /var/lib/postgresql/17/main -U replica_user -P -W -R
sudo chown -R postgres:postgres /var/lib/postgresql/17/main

Configure replica server postgresql.conf

Set up the replica server with hot standby mode and configure streaming replication parameters.

# Connection settings
listen_addresses = '*'
port = 5432
max_connections = 200

Standby settings

hot_standby = on max_standby_streaming_delay = 30s wal_receiver_status_interval = 10s hot_standby_feedback = on

Archive recovery

restore_command = 'cp /var/lib/postgresql/17/main/archive/%f %p' archive_cleanup_command = 'pg_archivecleanup /var/lib/postgresql/17/main/archive %r'

Performance

shared_buffers = 256MB wal_buffers = 16MB

Configure replica recovery settings

The pg_basebackup command with -R flag automatically creates the standby.signal file and primary connection settings.

sudo -u postgres ls -la /var/lib/postgresql/17/main/standby.signal
sudo -u postgres cat /var/lib/postgresql/17/main/postgresql.auto.conf

Start replica server

Start the replica PostgreSQL server which will automatically connect to the primary and begin streaming replication.

sudo systemctl start postgresql
sudo systemctl status postgresql

Install and configure pg_auto_failover monitor

Set up the pg_auto_failover monitor node that manages automatic failover decisions and cluster state.

sudo -u postgres pg_autoctl create monitor --hostname 203.0.113.30 --pgdata /var/lib/postgresql/monitor --pgport 5433
sudo -u postgres pg_autoctl -q show systemd --pgdata /var/lib/postgresql/monitor > /tmp/pgautofailover.service
sudo mv /tmp/pgautofailover.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable pgautofailover
sudo systemctl start pgautofailover

Register primary server with pg_auto_failover

Register the primary PostgreSQL server with the failover monitor to enable automatic failover management.

sudo -u postgres pg_autoctl create postgres --hostname 203.0.113.10 --pgdata /var/lib/postgresql/17/main --monitor postgres://autoctl_node@203.0.113.30:5433/pg_auto_failover --pgport 5432
sudo -u postgres pg_autoctl -q show systemd --pgdata /var/lib/postgresql/17/main > /tmp/pgautofailover-primary.service
sudo mv /tmp/pgautofailover-primary.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable pgautofailover-primary
sudo systemctl start pgautofailover-primary

Register replica server with pg_auto_failover

Register the replica server with the monitor to complete the high availability cluster setup.

sudo systemctl stop postgresql
sudo -u postgres pg_autoctl create postgres --hostname 203.0.113.20 --pgdata /var/lib/postgresql/17/main --monitor postgres://autoctl_node@203.0.113.30:5433/pg_auto_failover --pgport 5432
sudo -u postgres pg_autoctl -q show systemd --pgdata /var/lib/postgresql/17/main > /tmp/pgautofailover-replica.service
sudo mv /tmp/pgautofailover-replica.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable pgautofailover-replica
sudo systemctl start pgautofailover-replica

Configure firewall rules

Open the necessary ports for PostgreSQL replication and pg_auto_failover communication between servers.

sudo ufw allow from 203.0.113.0/24 to any port 5432
sudo ufw allow from 203.0.113.0/24 to any port 5433
sudo ufw reload
sudo firewall-cmd --permanent --add-rich-rule="rule family='ipv4' source address='203.0.113.0/24' port protocol='tcp' port='5432' accept"
sudo firewall-cmd --permanent --add-rich-rule="rule family='ipv4' source address='203.0.113.0/24' port protocol='tcp' port='5433' accept"
sudo firewall-cmd --reload

Verify your setup

Check replication status and cluster health with these verification commands.

# Check replication status
sudo -u postgres psql -c "SELECT client_addr, state, sync_state FROM pg_stat_replication;"

Check cluster status

sudo -u postgres pg_autoctl show state

Check monitor status

sudo -u postgres pg_autoctl show events
# Create test data on primary
sudo -u postgres psql -c "CREATE TABLE replication_test (id SERIAL PRIMARY KEY, created_at TIMESTAMP DEFAULT NOW());"
sudo -u postgres psql -c "INSERT INTO replication_test DEFAULT VALUES;"

Verify on replica (read-only)

sudo -u postgres psql -h 203.0.113.20 -c "SELECT * FROM replication_test;"

Monitoring and maintenance procedures

Set up monitoring queries

Create monitoring queries to track replication lag and cluster health. These can be integrated with your existing monitoring infrastructure.

-- Check replication lag
SELECT 
    client_addr,
    application_name,
    state,
    pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), flush_lsn)) AS lag
FROM pg_stat_replication;

-- Check cluster formation
SELECT * FROM pgautofailover.formation;

Configure automated backup verification

Set up automated testing of your replica to ensure it can be promoted successfully during maintenance windows.

#!/bin/bash

Test failover readiness

echo "Checking replica lag..." sudo -u postgres psql -h 203.0.113.20 -c "SELECT pg_last_wal_receive_lsn(), pg_last_wal_replay_lsn();"

Check if replica is ready for promotion

echo "Checking failover readiness..." sudo -u postgres pg_autoctl show state --formation default --group 0
chmod +x /home/postgres/test_failover.sh
sudo chown postgres:postgres /home/postgres/test_failover.sh

Set up log rotation for PostgreSQL

Configure log rotation to prevent disk space issues and maintain performance monitoring data.

/var/log/postgresql/*.log {
    daily
    rotate 30
    compress
    delaycompress
    missingok
    notifempty
    postrotate
        /bin/systemctl reload postgresql >/dev/null 2>&1 || true
    endscript
}
Warning: Always test failover procedures in a non-production environment first. Automatic failover can result in data loss if not properly configured.

Common issues

SymptomCauseFix
Replica server cannot connectAuthentication failure or firewall blockingCheck pg_hba.conf entries and firewall rules. Verify replica_user password.
Replication lag increasingNetwork issues or high write loadCheck network connectivity and consider increasing wal_buffers or wal_keep_size.
pg_auto_failover not respondingMonitor node unreachableCheck monitor node status: sudo systemctl status pgautofailover
Archive directory filling upWAL files not being cleanedVerify archive_cleanup_command is working: check /var/lib/postgresql/17/main/archive/
Failed to promote replicaInsufficient permissions or corrupted WALCheck postgres user owns all files: sudo chown -R postgres:postgres /var/lib/postgresql/
Connection pooling errorsToo many connections during failoverConfigure connection pooling with PgBouncer

Next steps

Automated install script

Run this to automate the entire setup

Need help?

Don't want to manage this yourself?

We handle high availability infrastructure for businesses that depend on uptime. From initial setup to ongoing operations.