What is High Availability for Odoo?
High availability (HA) means your Odoo system survives server failures without downtime. In a standard deployment, if your server dies, Odoo is offline until you restore it — potentially hours of lost productivity and revenue. With HA, a standby server takes over automatically within seconds.
HA is essential for businesses where Odoo downtime means lost sales (e-commerce), halted manufacturing, or regulatory compliance issues.
HA Architecture
Floating IP
↓
┌─────────┼─────────┐
↓ ↓
Active Node Standby Node
┌────────┐ ┌────────┐
│ nginx │ │ nginx │
│ Odoo │ │ Odoo │
│ PG Pri │────────→│ PG Rep │
└────────┘ stream └────────┘
replication
Keepalived monitors health and
moves floating IP on failureComponents
| Component | Purpose | Tool |
|---|---|---|
| Floating IP | Single entry point that moves between servers | Cloud provider API or Keepalived |
| Health monitoring | Detect failures and trigger failover | Keepalived, HAProxy |
| Database replication | Keep standby DB in sync | PostgreSQL streaming replication |
| Filestore sync | Keep attachments in sync | lsyncd, rsync, or S3 |
| Automatic promotion | Promote replica to primary on failure | Patroni, repmgr, or custom scripts |
Step 1: Set Up PostgreSQL Replication
# On PRIMARY server
sudo -u postgres psql
CREATE ROLE replicator WITH REPLICATION LOGIN PASSWORD 'rep_password';
# postgresql.conf
wal_level = replica
max_wal_senders = 5
wal_keep_size = 2048
synchronous_standby_names = 'standby1'
# pg_hba.conf
host replication replicator STANDBY_IP/32 scram-sha-256
sudo systemctl restart postgresql# On STANDBY server
sudo systemctl stop postgresql
sudo -u postgres rm -rf /var/lib/postgresql/16/main/*
sudo -u postgres pg_basebackup -h PRIMARY_IP -U replicator \
-D /var/lib/postgresql/16/main -P -R
# The -R flag creates standby.signal and configures primary_conninfo
sudo systemctl start postgresqlStep 2: Install Patroni for Automatic Failover
Patroni manages PostgreSQL HA with automatic failover, leader election, and cluster management:
# Install on both nodes
pip install patroni[etcd]
# patroni.yml (primary)
scope: odoo-cluster
name: node1
restapi:
listen: 0.0.0.0:8008
connect_address: PRIMARY_IP:8008
etcd:
hosts: ETCD_HOST:2379
bootstrap:
dcs:
ttl: 30
loop_wait: 10
retry_timeout: 10
maximum_lag_on_failover: 1048576
postgresql:
use_pg_rewind: true
parameters:
wal_level: replica
max_wal_senders: 5
max_replication_slots: 5
postgresql:
listen: 0.0.0.0:5432
connect_address: PRIMARY_IP:5432
data_dir: /var/lib/postgresql/16/main
authentication:
superuser:
username: postgres
password: pg_password
replication:
username: replicator
password: rep_passwordStep 3: Configure Keepalived for Floating IP
# On primary node: /etc/keepalived/keepalived.conf
vrrp_script check_odoo {
script "/usr/bin/curl -s -o /dev/null -w '%{http_code}' http://localhost:8069/web/health | grep -q 200"
interval 5
weight -20
fall 3
rise 2
}
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass secret123
}
virtual_ipaddress {
FLOATING_IP/32
}
track_script {
check_odoo
}
notify_master "/opt/scripts/promote.sh"
}
# On standby node: same config but
# state BACKUP, priority 90Step 4: Filestore Synchronization
# Option A: lsyncd (real-time sync)
apt install lsyncd
# /etc/lsyncd.conf
settings {
logfile = "/var/log/lsyncd.log",
statusFile = "/var/log/lsyncd-status.log",
}
sync {
default.rsync,
source = "/opt/odoo/data/filestore",
target = "standby:/opt/odoo/data/filestore",
delay = 5,
rsync = {
archive = true,
compress = true,
}
}
# Option B: S3 (shared object storage)
# Both nodes use S3 for filestore — no sync neededStep 5: Failover Promotion Script
#!/bin/bash
# /opt/scripts/promote.sh
# Called by Keepalived when this node becomes MASTER
logger "Odoo HA: Promoting standby to primary"
# Promote PostgreSQL (if using manual replication, not Patroni)
sudo -u postgres pg_ctl promote -D /var/lib/postgresql/16/main
# Start Odoo if not running
sudo systemctl start odoo
# Notify team
curl -X POST https://hooks.slack.com/services/xxx \
-d '{"text": "Odoo failover completed. Standby promoted to primary."}'Testing Failover
Regularly test your HA setup:
- Simulate failure: stop Odoo on the primary node
- Verify Keepalived detects failure within 15 seconds
- Verify floating IP moves to standby
- Verify standby PostgreSQL is promoted
- Verify users can continue working with minimal disruption
- Restore original primary and test failback
RTO and RPO
| Metric | No HA | Basic HA | Full HA (Patroni) |
|---|---|---|---|
| Recovery Time (RTO) | 1-4 hours | 30-60 seconds | 10-30 seconds |
| Data Loss (RPO) | Last backup | Seconds (async) | Zero (sync replication) |
| Annual downtime | Hours | Minutes | Seconds |
DeployMonkey + High Availability
DeployMonkey offers HA configurations for business-critical Odoo deployments. Automatic failover, database replication, and health monitoring are handled transparently.