When running business-critical applications like Odoo, database uptime and reliability are non-negotiable. PostgreSQL, though robust, requires an external setup to achieve true high availability (HA). That’s where Patroni comes in — an open-source cluster management solution for PostgreSQL that automates failover, replication, and recovery.
In this post, we’ll explore how we achieved high availability for PostgreSQL in our Odoo setup using Patroni, etcd, Keepalived, and a virtual IP (VIP). Importantly, we chose to keep things simple by avoiding SSL in our internal network to eliminate connection overhead and ensure faster Odoo performance.
Why High Availability Matters
Databases are at the heart of every enterprise system. If the primary PostgreSQL server goes down, applications like Odoo grind to a halt. HA ensures that:
- Downtime is minimized — automatic failover promotes a standby node to primary.
- Data consistency is maintained — replication ensures standbys are always up to date.
- Applications remain connected — clients (like Odoo) don’t need to know which node is primary.
Without HA, every database outage would mean manual intervention, longer downtime, and unhappy users.
Our HA Architecture
We designed a three-node setup that balances performance and resilience:
- Node 1: PostgreSQL + Patroni
- Node 2: PostgreSQL + Patroni
- Node 3: etcd + Keepalived
- VIP: Managed by Keepalived, used by Odoo to connect
Here’s how the pieces fit together:
- Patroni runs on the database nodes, managing PostgreSQL replication and failover.
- etcd provides a distributed key-value store where Patroni coordinates leadership and cluster state.
- Keepalived manages a floating virtual IP (VIP) that always points to the active primary node.
- Odoo connects only to the VIP (10.0.20.155:5432), completely abstracting away which physical node is currently the leader.
This way, when the primary node fails, Patroni triggers failover, etcd updates the cluster state, and Keepalived ensures the VIP moves seamlessly to the new primary. Odoo keeps running without disruption. Here’s the purpose of each component we have:
Patroni
- Automated Replication & Failover: Patroni is the automation layer that keeps PostgreSQL highly available. It manages streaming replication between nodes and constantly monitors the cluster’s health. If the primary node becomes unavailable, Patroni promotes a standby to primary automatically, reducing downtime and avoiding manual intervention.
- Cluster Orchestration & API: Patroni uses a distributed consensus store (like etcd) to coordinate decisions. It also provides a REST API, allowing administrators or tools to query cluster status, trigger manual switchovers, or integrate with monitoring systems. This makes Patroni the “brain” of the HA cluster.
etcd
- Reliable Consensus Store: etcd is a distributed key-value store that keeps critical cluster metadata, such as the current primary and replica nodes. It ensures consistency across all nodes using the Raft consensus algorithm, preventing “split-brain” scenarios where multiple nodes think they’re the primary.
- Coordination Backbone for Patroni: Patroni relies on etcd to store leader election results and share cluster state. Because etcd requires an odd number of members (e.g., 3, 5), it guarantees quorum, ensuring high reliability. Without etcd, Patroni would have no reliable way to coordinate failovers.
HAProxy
- Traffic Routing to Primary: HAProxy is a load balancer that can direct database traffic to the correct PostgreSQL node. By integrating with Patroni’s REST API, it knows which node is primary and ensures all write traffic is routed there, keeping applications consistent.
- Health Checks & Failover Handling: HAProxy performs continuous health checks on PostgreSQL nodes. If a primary node fails, it automatically routes traffic to the new primary after failover. This ensures applications like Odoo stay connected without requiring reconfiguration.
Keepalived
- Virtual IP Management: Keepalived provides a floating virtual IP (VIP) that always points to the active primary database node. Applications connect only to the VIP, not the physical IPs of individual servers. This makes failovers transparent to applications like Odoo.
- High Availability via VRRP: Keepalived uses the VRRP (Virtual Router Redundancy Protocol) to move the VIP between nodes based on health checks. If the node hosting the VIP fails, Keepalived reassigns it to a healthy node, ensuring uninterrupted database connectivity.
Why We Skipped HAProxy
Many HA setups include HAProxy to route database traffic. While it works, we found that in our case, Odoo became noticeably slower due to the extra network hop. Since we’re running in a trusted internal environment, we opted to skip HAProxy and let Keepalived handle traffic redirection with the VIP.
This simplification gave us two major benefits:
- Reduced latency for Odoo connections.
- Fewer moving parts to maintain.
How Failover Works in This Setup
- Odoo connects to the VIP (10.0.20.155).
- The VIP points to whichever PostgreSQL node is currently the primary.
- If the primary fails, Patroni detects the issue and promotes the standby.
- etcd updates the cluster metadata with the new leader.
- Keepalived moves the VIP to the new primary node.
- Odoo stays connected to the same IP, without noticing the failover.
From the application’s perspective, nothing changes — and that’s the whole point of high availability.
By combining Patroni, etcd, and Keepalived, we built a highly available PostgreSQL cluster for Odoo without relying on SSL or HAProxy. This approach ensures:
- Continuous database availability
- Automatic failover with minimal downtime
- A simple, single-point connection for Odoo
For businesses running mission-critical apps like Odoo, this kind of setup ensures resilience without adding unnecessary complexity.