If you run PostgreSQL in production at any scale, you’ve probably already adopted Patroni to manage high availability within a single cluster. Patroni watches your nodes, holds a leader lock in a distributed configuration store (DCS) like etcd, ZooKeeper, or Consul, and automatically promotes a replica when the primary fails. That solves the “a node died” problem. But it doesn’t solve a much bigger problem: what happens when an entire datacenter, region, or availability zone goes dark?
This is where Patroni’s standby cluster feature comes in. It’s one of the more powerful capability in the Patroni toolkit. A standby cluster lets you run a fully independent, self-healing Patroni cluster in a second location that continuously streams data from a primary cluster elsewhere — without merging the two clusters’ HA control planes into a single, fragile, cross-datacenter consensus group.
In this post, we’ll go deep on what a standby cluster actually is, how it differs from a “regular” replica, how to configure one. By the end, you should have a solid mental model for deciding whether a standby cluster is the right tool for your disaster recovery strategy, and enough detail to actually set one up.
The Problem Standby Clusters Solve
A standard Patroni cluster is a set of PostgreSQL nodes plus a DCS quorum, all living in roughly the same failure domain — usually one datacenter or one cloud region. Patroni uses the DCS to hold a leader key; whichever node holds the key is the primary, and Patroni orchestrates replication, failover, and switchover among the members.
The trouble starts when you try to stretch that same design across two datacenters. You could, in theory, deploy a single etcd cluster spanning both sites and let Patroni fail over between them automatically. But now every write to the DCS — every heartbeat, every leader-lock renewal — has to cross a WAN link with real latency and a real chance of partition. A network blip between datacenters can trigger split-brain scenarios, unnecessary failovers, or an unavailable leader lock that stalls writes on both sides. Patroni’s own multi-datacenter documentation is candid about this: stretching one DCS quorum across sites works, but it requires careful thought about node counts per zone and synchronous replication, and it still leaves you exposed to WAN-partition pathologies.
Standby clusters sidestep this entirely by refusing to merge the control planes. Instead, you run two (or more) completely separate Patroni clusters, each with its own independent DCS quorum, each capable of electing its own leader locally. The only thing connecting them is a PostgreSQL streaming replication link: one cluster’s leader ships WAL to the other cluster’s leader. Everything else — leader election, health checking, automatic failover of replicas within each site — happens locally, at LAN speed, with no cross-site dependency for day-to-day operation.
What a Standby Cluster Actually Is
A Patroni standby cluster has this shape:
- A standby leader: a node that behaves like a normal cluster leader from the point of view of its own local cluster — it holds the leader lock in its local DCS, and other nodes in that cluster replicate from it. But unlike a “real” primary, the standby leader is itself a PostgreSQL hot-standby replica, streaming from a node in the remote (primary) cluster.
- Cascading replicas: additional nodes within the standby cluster that replicate from the standby leader, exactly the way normal replicas replicate from a normal leader.
If the standby leader’s lock expires (say the node crashes), the remaining cascading replicas in the standby cluster hold their own local election and promote one of themselves to be the new standby leader — again, entirely within that cluster’s own DCS, with no coordination needed from the primary side.
Critically, the two clusters are otherwise strangers to each other. There is no requirement that they share a DCS scope, and if they do happen to use the same DCS technology, they must use different scopes or namespaces, or you risk key collisions between two clusters that don’t know about each other’s existence. The primary cluster doesn’t even show the standby cluster in its own patronictl list or patronictl topology output — as far as the primary’s Patroni is concerned, the standby cluster’s leader is just another replication client connecting over streaming replication.
This is a deliberate design choice. The relationship is purely a PostgreSQL streaming replication relationship, layered underneath two independently operating Patroni HA domains. That’s what makes the architecture resilient to WAN partitions: if the link between sites drops, each side keeps functioning as a normal, healthy, independently-managed cluster. The standby side just stops receiving new WAL until the link recovers.
Core Use Cases
Before diving into configuration, it’s worth being explicit about why teams reach for this feature. The most common motivations fall into a few buckets:
- Disaster recovery across datacenters or regions. If your primary datacenter suffers an outage — a fire, a network provider failure, a natural disaster — you want a warm, ready-to-promote copy of your database sitting in a different physical location, with its own independent HA management, ready to take over traffic.
- Migrating to new hardware or a new environment. Rather than doing an in-place upgrade or a risky pg_upgrade dance, you can stand up a brand-new Patroni cluster on new infrastructure as a standby cluster, let it catch up via streaming replication, validate it thoroughly, and then cut over when you’re confident, with minimal downtime.
- Read scaling in a secondary region. A standby cluster’s replicas can serve read traffic close to users in a different geography, while all writes continue to flow to the primary cluster’s region.
- Zero-downtime major version or platform migrations. Because the standby cluster is a fully separate Patroni deployment, you can use it as a staging ground to validate configuration changes, extension upgrades, or OS-level changes before promoting it to be the new source of truth.
How to configure Standby Cluster
Open the video alongside this post to see each configuration step applied live — from creating the permanent replication slot on the primary, through the standby_cluster block on the standby side, to the first successful streaming connection between the two independent clusters.
Conclusion
Standby clusters are Patroni’s answer to a problem that a single stretched cluster handles poorly: keeping high availability fast and local while still giving you a real, warm copy of your data somewhere else entirely. By refusing to merge control planes — keeping leader election, health checks, and failover fully independent on each side — Patroni sidesteps the split-brain and WAN-partition risks that come with spanning one DCS quorum across datacenters. Each site stays simple and self-healing on its own; the only thing crossing the WAN is a plain streaming replication connection.
That simplicity is also what makes standby clusters so versatile. The same mechanism that gives you disaster recovery across regions is equally useful for staging a hardware migration, validating an upgrade before cutover, or serving reads closer to users in a second geography — all without touching your primary cluster’s HA topology.
The configuration itself is intentionally minimal: a permanent replication slot and a pg_hba entry on the primary side, a standby_cluster block pointing at the primary (ideally via a floating VIP) on the standby side, and Patroni takes care of everything else — bootstrapping, cascading replication within the standby cluster, and even standby-leader failover if a node goes down. If you want to see this actually built and verified end to end, check out the walkthrough video below.
