When it comes to achieving high availability and failover support in PostgreSQL, streaming replication is one of the most reliable mechanisms. To make the setup easier and more efficient, tools like repmgr are often used.
This blog is completely based on configuring streaming replication using repmgr 5.5.0 on PostgreSQL 17 by downloading and building two PostgreSQL source codes of version 17 on the same laptop — one acting as the primary server and the other as the standby server.
In this blog, we will walk you through the step-by-step process of how to achieve streaming replication using repmgr, including all commands, configuration details, and important tips along the way.
Why Streaming Replication and Why repmgr?
Streaming replication is a process where the primary server continuously streams WAL (Write-Ahead Logging) files to one or more standby servers. This ensures that the standby remains an exact copy of the primary database and can quickly take over if the primary fails.
Setting it up manually can be complex, especially when managing multiple nodes. That’s where repmgr comes in. It simplifies the administration of PostgreSQL replication clusters by offering easy-to-use commands for cloning, registering nodes, and monitoring cluster health.
Setting Up the Environment
Setting Up PostgreSQL 17 from Source for the Primary Server
# Create a directory to hold the PostgreSQL source code
mkdir ~/postgres_code
cd ~/postgres_code
# Clone the PostgreSQL 17 source code
git clone https://git.postgresql.org/git/postgresql.git -b REL_17_STABLE
# Enter the cloned repository
cd postgresql
# Configure PostgreSQL with necessary options
./configure --prefix=$(pwd) --enable-cassert --enable-debug
# Build and install
make
make install
This setup will act as the Primary Server.
Setting Up PostgreSQL 17 from Source for the Standby Server
# Create a separate directory for the standby server
mkdir ~/postgres_17_new
cd ~/postgres_17_new
# Clone the same PostgreSQL 17 source code
git clone https://git.postgresql.org/git/postgresql.git -b REL_17_STABLE
# Enter the cloned repository
cd postgresql
# Configure PostgreSQL
./configure --prefix=$(pwd) --enable-cassert --enable-debug
# Build and install
make
make install
This setup will act as the Standby Server.
Step 1: Building the PostgreSQL Servers
First, I built two separate instances of PostgreSQL
# For the primary server
# Navigate to the postgres source code’s directory in terminal (act as primary server)
cd posgres_code/postgres
bin/initdb test_1
bin/pg_ctl -D test_1 -o '-p 5432' -l logfile start
bin/psql -p 5432 postgres
# For the standby server
# Navigate to the postgres source code’s directory in terminal (act as secondary server)
cd postgres_17_new/postgres
bin/initdb test_2
# Update postgresql.conf to use a different port
# Change port to 5433
bin/pg_ctl -D test_2 -o '-p 5433' -l logfile start
bin/psql -p 5433 postgres
Now, we have:
Primary PostgreSQL server running on port 5432
Standby PostgreSQL server running on port 5433
Step 2: Preparing the Primary Server
In the primary instance, I created a repmgr user and a repmgr database:
CREATE USER repmgr WITH SUPERUSER LOGIN PASSWORD 'abc';
CREATE DATABASE repmgr OWNER repmgr;
Then, I created a repmgr.conf file inside the primary's data directory (test_1) with the following content:
node_id=1
node_name=primary
conninfo='host=localhost user=repmgr dbname=repmgr port=5432'
data_directory='/home/cybrosys/postgres_code/postgresql/test_1'
Step 3: Installing repmgr
After setting up PostgreSQL instances, downloaded and installed repmgr 5.5.0 from the source code.
# 1. Clone and switch version
git clone https://github.com/EnterpriseDB/repmgr.git
cd repmgr
git checkout v5.5.0
# 2. For Master PostgreSQL
export PATH='/home/cybrosys/postgres_code/postgresql/bin:'"$PATH"
./configure
make USE_PGXS=1
sudo make install
After this installation, go to postgres.conf file of data directory of master postgres to set this line
Shared_preload_libraries = ‘repmgr’
# 3. For Standby PostgreSQL
export PATH='/home/cybrosys/postgres_17_new/postgresql/bin:'"$PATH"
make clean
make USE_PGXS=1
sudo make install
After this installation, go to postgres.conf file of data directory of standby postgres to set this line
shared_preload_libraries = ‘repmgr’
Once installed, registered the primary server with repmgr:
repmgr -f /home/cybrosys/postgres_code/postgresql/test_1/repmgr.conf primary register
If everything is correct, you’ll see messages like:
INFO: connecting to primary database...
NOTICE: "repmgr" extension successfully installed
NOTICE: primary node record (ID: 1) registered
Step 4: Cloning the Standby Server
Next, I cloned the primary server’s data directory into the standby's data directory using repmgr:
repmgr -h localhost -U repmgr -d repmgr -p 5432 -D /home/cybrosys/postgres_17_new/postgresql/test_2 standby clone --force
During the process, repmgr internally uses pg_basebackup to copy all data from the primary to the standby.
Step 5: Configuring the Standby Server
I created a new repmgr.conf for the standby server:
node_id=2
node_name=standby
conninfo='host=localhost user=repmgr dbname=repmgr port=5433'
data_directory='/home/cybrosys/postgres_17_new/postgresql/test_2'
Also, I made sure the postgresql.conf of standby listens on port 5433.
Now, I registered the standby server:
repmgr -f /home/cybrosys/postgres_17_new/postgresql/test_2/repmgr.conf standby register --force
Step 6: Setting Up primary_conninfo
For the standby server to connect back to the primary server for streaming WALs, we need to set the primary_conninfo parameter:
ALTER SYSTEM SET primary_conninfo = 'host=localhost port=5432 user=repmgr dbname=repmgr password=abc application_name=standby';
SELECT pg_reload_conf();
You can verify:
SHOW primary_conninfo;
The output should correctly show:
host=localhost user=repmgr port=5432 application_name=standby
Step 7: Verifying the Cluster Status
ID | Name | Role | Status | Upstream | Location | Priority | Timeline | Connection string |
1 | primary | standby | * running |
| default | 100 | 1 | host=localhost user=repmgr dbname=repmgr port=5432 |
2 | primary | standby | running | Primary | default | 100 | 1 | host=localhost user=repmgr dbname=repmgr port=5433 |
This confirms that the primary and standby are correctly connected and replication is active.
Step 8: Setting Up Monitoring Daemons
To monitor the primary and standby nodes automatically, we run the repmgrd daemon:
For the Primary server monitoring:
repmgrd -f /home/cybrosys/postgres_code/postgresql/test_1/repmgr.conf --pid-file /tmp/repmgrd-primary.pid --daemonize
Here, we are starting the repmgrd daemon for the primary server and saving its process ID (PID) into a file called /tmp/repmgrd-primary.pid.
For the Standby server monitoring:
repmgrd -f /home/cybrosys/postgres_17_new/postgresql/test_2/repmgr.conf --pid-file /tmp/repmgrd-standby.pid --daemonize
Here, we are starting another repmgrd daemon, but this time for the standby server, and saving its PID separately in /tmp/repmgrd-standby.pid.
Why different --pid-file names for primary and standby?
Because both repmgrd processes (primary and standby) are running on the same machine!
Each repmgrd process needs its own unique PID file so that:
You can individually monitor, restart, or stop each repmgrd daemon.
It avoids conflicts — if both tried to write to the same PID file, they would overwrite each other's info and crash or behave unpredictably.
It helps identify which process is primary and which is for standby, easily.
So giving different --pid-file paths ensures safe and smooth monitoring of both primary and standby PostgreSQL servers on the same system.
Final Notes
* built two PostgreSQL 17 instances from source manually.
* Installed repmgr 5.5.0 and configured both nodes.
* Configured streaming replication successfully with automatic monitoring using repmgrd.
* All setup was performed on a single laptop by using different ports (5432 and 5433).
Conclusion
Setting up streaming replication manually can be challenging, but repmgr truly simplifies the process, making it clean, efficient, and highly manageable.
With proper configuration, repmgr also ensures smooth failover and recovery scenarios, making your PostgreSQL setup highly available and reliable.