Info2soft use cookies to help you have a superior and more admissible browsing experience on our website. Privacy Policy
Loading...
Patroni is an open-source Python-based framework for building highly available PostgreSQL clusters. It manages PostgreSQL instances and coordinates leader election through a distributed configuration store (DCS) such as etcd, Consul, ZooKeeper, or Kubernetes. Unlike manual replication setups, Patroni eliminates the risk of split-brain and ensures that only one primary node exists at any time. This makes it ideal for mission-critical applications requiring for 9.99% uptime.
In this Patroni PostgreSQL setup guide, you will know how to build a Patroni PostgreSQL cluster with detailed steps.
Professional high-availability solution designed for critical workloads across physical, virtual, and hybrid environments. Automated failover, Near-zero RPO and RTO.
A typical Patroni PostgreSQL cluster consists of PostgreSQL, Patroni, a distributed configuration store (DCS), and usually a client connection layer to provide automated high availability. Each component has a different responsibility.
Before beginning your setup, verify that your infrastructure, operating system, and network configuration meet requirements to support a stable, highly available cluster.
1. For database nodes, a minimum of 2 servers (1 primary + 1 standby), but 3 nodes are recommended for full redundancy during maintenance or unplanned outages.
2. For the distributed configuration store (DCS), a 3-node etcd cluster
3. For production environments, deploy etcd nodes on separate servers from PostgreSQL nodes.
4. Ensure all nodes have Python 3 and pip installed, as well as access to the official PostgreSQL PGDG repository for certified packages.
5. All cluster components must be able to communicate reliably. At minimum, plan connectivity for:
|
Component |
Typical Port |
Purpose |
|
PostgreSQL |
5432 |
Database connections and replication |
|
Patroni |
8008 |
Health checks and cluster management |
|
etcd |
2379/2380 |
Client and peer communication |
This PostgreSQL Patroni tutorial will guide you on how to set up PostgreSQL high availability with Patroni, including package installation to running a multi-node cluster.
We use etcd as the DCS (the most common production choice) and Debian/Ubuntu as the base OS, with notes for cross-platform equivalents where applicable.
First, enable the official PostgreSQL PGDG repository to get latest packages:
sudo apt install -y postgresql-common
sudo /usr/share/postgresql-common/pgdg/apt.postgresql.org.sh
Next, install your target PostgreSQL version.
sudo apt install -y postgresql-16 postgresql-contrib-16
Once installed, stop the default PostgreSQL systemd service and disable it entirely. Patroni will start, stop, and configure PostgreSQL on its own schedule, so the OS-level service must not interfere:
sudo systemctl stop postgresq
sudo systemctl disable postgresql
Finally, remove the default pre-created database cluster. Patroni will initialize a fresh cluster with its own configuration during bootstrap:
sudo pg_dropcluster 16 main
This clean state ensures Patroni has full control over PostgreSQL configuration, data directories, and replication setup without conflicts from package defaults.
There are two primary installation methods: system packages (recommended for Debian/RHEL) and pip (for latest versions or custom setups).
Option 1 – Install via system package (Debian/Ubuntu):
The PGDG repository includes a maintained Patroni package. Install it with:
sudo apt install -y patroni
Option 2 – Install via Pip (cross-platform)
For systems without official packages, or to use the latest Patroni release with etcd v3 support, install via pip:
sudo apt install -y python3 python3-pip
sudo pip3 install patroni[etcd3]
Verify the installation with:
patroni --version
You can add the etcd settings directly to your main Patroni YAML file. For a 3-node etcd cluster, the configuration block looks like this:
etcd3:
hosts: 10.0.0.1:2379,10.0.0.2:2379,10.0.0.3:2379
Pay close attention to the etcd3 key name rather than plain etcd. Patroni defaults to the legacy etcd2 protocol for backward compatibility. Using etcd3 is required for etcd versions 3.0 and above, which are standard in all current production environments.
YAMAL is critical for setup. It defines node identity, DCS connection, bootstrap behavior, PostgreSQL settings, and replication rules.
The following is a production-ready configuration, with explanations for each key component.
Global & Node Identity Settings
scope: postgres-cluster
namespace: /db/
name: pg-node1
DCS Behavior Settings
bootstrap:esxcli storage filesystem list
dcs:
ttl: 30
loop_wait: 10
retry_timeout: 10
maximum_lag_on_failover: 1048576
primary_start_timeout: 300
synchronous_mode: false
PostgreSQL Bootstrap Settings
Still under the bootstrap.dcs section, define PostgreSQL parameters and access controls that apply cluster-wide:
postgresql:
use_pg_rewind: true
use_slots: true
parameters:
wal_level: replica
hot_standby: on
max_connections: 200
shared_buffers: 2GB
effective_cache_size: 6GB
pg_hba:
- host replication replicator 10.0.0.0/24 scram-sha-256
- host all all 10.0.0.0/24 scram-sha-256
- local all all peer
Local PostgreSQL Node Settings
The top-level postgresql section configures the local PostgreSQL instance on this specific node:
postgresql:
listen: 0.0.0.0:5432
connect_address: 10.0.0.11:5432
data_dir: /var/lib/postgresql/16/main
bin_dir: /usr/lib/postgresql/16/bin
authentication:
replication:
username: replicator
password: replicator_password
superuser:
username: postgres
password: postgres_password
create_replica_methods:
- basebackup
basebackup:
max-rate: '100M'
With configuration in place, start the cluster one node at a time. The first node you start will initialize the cluster and become the initial primary (leader).
First, set correct permissions on the configuration and data directories:
sudo mkdir -p /var/lib/postgresql/16/main
sudo chown -R postgres:postgres /var/lib/postgresql/16
sudo chown postgres:postgres /etc/patroni/patroni.yml
Enable and start the Patroni systemd service on the first node only:
sudo systemctl daemon-reload
sudo systemctl enable patroni
sudo systemctl start patroni
Wait 30–60 seconds for the first node to bootstrap the cluster. Then start Patroni on the remaining replica nodes using the same commands. Each replica will automatically detect the existing primary via the DCS, run a basebackup to clone the data directory, and begin streaming replication
Tip: If you want a specific node to be the initial primary, simply start Patroni on that node first and wait for it to claim the leader lease before starting the others
Once all nodes are running, verify the cluster status using the patronictl command-line utility. Run this from any node as the postgres user:
patronictl -c /etc/patroni/patroni.yml list
A healthy cluster will show output similar to this:
+ Cluster: postgres-cluster ----------+----+-----------+
| Member | Host | Role | State | Lag in MB |
+----------+------------+---------+-----------+-----------+
| pg-node1 | 10.0.0.11 | Leader | running | |
| pg-node2 | 10.0.0.12 | Replica | streaming | 0.0 |
| pg-node3 | 10.0.0.13 | Replica | streaming | 0.0 |
+----------+------------+---------+-----------+-----------+
Confirm that:
You can also verify direct PostgreSQL connectivity to confirm the database is accessible:
psql -h 10.0.0.11 -p 5432 -U postgres -c "SELECT version();"
Basic Patroni PostgreSQL setup is complete. The next section will help you add a connection routing layer.
The basic setup delivers automated failover and streaming replication; direct client connections require tracking which node is the current primary and manually updating connection strings after every role change.
And HAProxy can act as a rasparent routing layer that provides stable, fixed endpoints for applications, while automatically detecting node roles and health status via Patroni’s built-in REST API.
Below are the steps to add HAProxy for Connection Routing
1. Install HAProxy
On Debian/Ubuntu systems, install HAProxy from the official distribution repositories:
sudo apt install haproxy -y
2. Configure HAProxy Backends
Edit the main configuration file at /etc/haproxy/haproxy.cfg to define two separate frontend-backend pairs: one for read-write primary traffic and one for read-only replica traffic.
global
maxconn 4096
defaults
mode tcp
timeout connect 5s
timeout client 30s
timeout server 30s
# Read-write endpoint (routes exclusively to the current primary)
frontend postgres_frontend
bind *:5000
default_backend postgres_backend
backend postgres_backend
option httpchk GET /primary
http-check expect status 200
default-server inter 3s fall 3 rise 2 on-marked-down shutdown-sessions
server pg-node1 10.0.0.11:5432 check port 8008
server pg-node2 10.0.0.12:5432 check port 8008
server pg-node3 10.0.0.13:5432 check port 8008
# Read-only endpoint (load-balances across all replicas)
frontend postgres_replica_frontend
bind *:5001
default_backend postgres_replica_backend
backend postgres_replica_backend
option httpchk GET /replica
http-check expect status 200
default-server inter 3s fall 3 rise 2
server pg-node1 10.0.0.11:5432 check port 8008
server pg-node2 10.0.0.12:5432 check port 8008
server pg-node3 10.0.0.13:5432 check port 8008
# Optional stats dashboard
listen stats
bind *:7000
stats enable
stats uri /
Key configuration notes:
3. Test Connection Strings
Restart HAProxy to apply the configuration:
sudo systemctl restart haproxy
Verify connectivity using standard PostgreSQL client tools. Connect to the read-write primary endpoint:
psql -h haproxy-host -p 5000 -U postgres -d postgres
Connect to the read-only replica endpoint for read-heavy workloads:
psql -h haproxy-host -p 5001 -U postgres -d postgres
With HAProxy deployed, your patroni postgresql cluster gains a production-ready access layer that fully decouples application connections from underlying node role changes and failover events.
Unlike traditional PostgreSQL replication deployments that require manual edits on every node, Patroni centralizes all cluster state in the DCS, so changes propagate consistently and automatically across all nodes. Below are how to manage your cluster.
`patronictl` is the main interface for cluster operations, and it is invoked using the `-c` flag to point to the local configuration file.
• View cluster health: Verify node roles, replication state, and lag — your primary diagnostic for cluster status:
patronictl -c /etc/patroni/patroni.yml list
• Planned switchover: Gracefully promote a replica to primary for scheduled maintenance with zero data loss:
patronictl -c /etc/patroni/patroni.yml switchover --candidate pg-node2
• Manual failover: Force a promotion when the current leader is unresponsive and automatic failover has not triggered:
patronictl -c /etc/patroni/patroni.yml failover --candidate pg-node3 --force
• Rolling restart: Apply configuration changes by restarting nodes sequentially with no cluster downtime:
patronictl -c /etc/patroni/patroni.yml restart postgres-cluster
• Reinitialize a replica: Rebuild a corrupted or out-of-sync replica from the primary via basebackup:
patronictl -c /etc/patroni/patroni.yml reinit postgres-cluster pg-node3
Cluster-wide PostgreSQL and Patroni settings are stored persistently in the DCS, overriding local defaults. Edit the full configuration interactively with:
patronictl -c /etc/patroni/patroni.yml edit-config
You can also update individual parameters directly, for example raising connection limits:
patronictl -c /etc/patroni/patroni.yml edit-config --set "postgresql.parameters.max_connections=300"
Changes apply to all nodes automatically. Parameters that require a PostgreSQL restart (such as wal_level or shared_buffers) can be rolled out via rolling restart to avoid downtime.
By default, Patroni uses asynchronous streaming replication, which optimizes for write throughput and low latency for most production workloads. The maximum_lag_on_failover parameter defines the acceptable data loss threshold during automatic failover.
For use cases requiring strict data durability, enable synchronous replication by setting synchronous_mode: true in the DCS. Patroni automatically manages PostgreSQL’s synchronous_standby_names to ensure every transaction is confirmed by at least one replica before commit, trading write performance for zero data loss on failover.
If your environment is simple and only running on PostgreSQL, Patroni is a good choice. But for organizations that need HA beyond PostgreSQL or want to protect the availability of the entire application and its underlying workload, i2Availability is a better choice.
i2Availability is an application-level high availability solution designed for critical workloads across physical, virtual, and hybrid environments. It uses real-time byte-level replication and automated failover to protect workloads and support business continuity with near-zero RPO and very low RTO.
Key strengths of i2Availability:
You can click the button below to request a 60-day free trial:
This is all for Patroni PostgreSQL setup. This process transforms standalone PostgreSQL into a resilient database platform with automated failover and consistent configuration management. It remains the ideal choice for pure PostgreSQL environments
For organizations requiring comprehensive business continuity, multi-database coverage, or long-distance cross-regional disaster recovery, Info2soft‘s i2Availability is more recommended.
· Enterprise & Mid-market Customers Worldwide
· Support team available to assist you throughout your trial
· Start a 60-day free trial or view demo to see how Info2Soft protects enterprise data.