High Availability with Patroni: The PostgreSQL HA Standard
Neither Data Guard Nor RAC
Oracle DBAs arrive at PostgreSQL expecting a Data Guard or RAC equivalent and find neither, exactly. PostgreSQL’s core ships streaming replication but deliberately not automatic failover. Promoting a standby when the primary dies — without two nodes both thinking they’re primary — is an orchestration problem, and Patroni is the de facto standard that solves it.
The architecture
- A Patroni agent on each node — it manages the local PostgreSQL (bootstrap, promote, demote, reconfigure) and reports health.
- A distributed consensus store (DCS) — etcd, Consul or ZooKeeper — that holds the leader lease. Exactly one node can hold it at a time; that node is the primary.
- A routing layer — HAProxy checking Patroni’s REST health endpoints, or a VIP — so clients always reach the current primary without knowing which node it is.
clients
│
HAProxy ──┐ (asks each node's Patroni REST API:
│ │ "are you the primary?")
┌────────┴────────┐
node A node B node C
Patroni Patroni Patroni
Postgres(primary) Postgres(replica) Postgres(replica)
└──────── DCS (etcd): holds the leader lease ────────┘How it avoids split-brain
The DCS leader lease is the whole trick. The primary must continually renew a time-limited lease in the DCS; if it can’t (crash, network partition), the lease expires, the other nodes hold an election, and the DCS grants the lease to exactly one new leader — which Patroni then promotes. A primary that loses the DCS steps itself down. Two primaries can’t both hold a single lease, so you don’t get split-brain.
Synchronous vs asynchronous: your failover trade-off
In asynchronous mode, failover is fast but can lose the last few transactions that hadn’t reached the standby yet. In synchronous mode, a commit isn’t acknowledged until a standby has it, so failover is lossless — at the cost of higher commit latency. Patroni lets you set this policy (including maximum_lag_on_failover) so a too-stale replica is never promoted.
Rejoining a failed primary: pg_rewind
When a crashed primary comes back, it can’t just rejoin — it may have WAL the new primary never saw. pg_rewind rewinds it to the point of divergence and turns it into a standby of the new primary, without a full re-clone. Patroni runs this automatically, which is what makes recovery hands-off.
How it compares to Data Guard / RAC
Patroni is failover HA (like Data Guard fast-start failover), not shared-storage clustering. PostgreSQL is shared-nothing — there is no RAC-style shared-everything cluster — so you scale reads with replicas and get availability through promotion. For the vast majority of workloads that’s not a limitation; it’s a simpler, cheaper operational model.
Land on PostgreSQL, then make it highly available
DBMigrateAIPro gets your data onto PostgreSQL with validation you can prove; Patroni gives it Data-Guard-level failover. Free for Year 1.
- 🔗 Download the desktop tool: medaxai.com
- 🔗 Related — PostgreSQL Streaming Replication: Zero to Production