What is Blue-Green Deployment?
Blue-green deployment maintains two identical production environments. One ("blue") serves live traffic while the other ("green") sits idle. When you deploy an update, you deploy to the idle environment, test it, then switch traffic. If something goes wrong, switch back instantly.
For Odoo, this eliminates the dreaded maintenance window where users see "System under maintenance" for 30-60 minutes during module upgrades. Instead, the switch happens in seconds.
Why Blue-Green for Odoo?
Odoo updates are risky. Module upgrades run database migrations, update views, and modify workflows. A failed upgrade can leave your system in an inconsistent state. Traditional deployment means:
- Notify users of downtime
- Stop Odoo
- Run backup (15-30 min for large DBs)
- Run module upgrade (
-u) (5-30 min) - Test (5-10 min)
- Start Odoo or rollback from backup (15-30 min)
Total: 30-90 minutes of downtime. With blue-green, users experience zero downtime, and rollback takes seconds instead of 30 minutes.
Architecture
DNS / Load Balancer
↓
┌───────────┼───────────┐
↓ ↓
Blue Environment Green Environment
┌─────────────┐ ┌─────────────┐
│ Odoo v1.0 │ │ Odoo v1.1 │
│ nginx │ │ nginx │
│ PG (copy) │ │ PG (copy) │
└─────────────┘ └─────────────┘
ACTIVE (serving) IDLE (updated, tested)Step 1: Set Up Two Environments
Create two identical server configurations. Use Docker to make this manageable:
# Blue environment (currently active)
docker compose -f docker-compose.blue.yml up -d
# Green environment (idle)
docker compose -f docker-compose.green.yml up -d# docker-compose.blue.yml
services:
odoo-blue:
image: your-registry/odoo:v1.0
ports:
- "8069:8069"
environment:
HOST: pg-blue
volumes:
- odoo-blue-data:/var/lib/odoo
- ./addons:/mnt/extra-addons
pg-blue:
image: postgres:16
volumes:
- pg-blue-data:/var/lib/postgresql/data
environment:
POSTGRES_USER: odoo
POSTGRES_PASSWORD: ${DB_PASSWORD}Step 2: Deployment Process
#!/bin/bash
# deploy.sh - Blue-green deployment script
CURRENT=$(cat /opt/deploy/active) # "blue" or "green"
if [ "$CURRENT" = "blue" ]; then
TARGET="green"
else
TARGET="blue"
fi
echo "Deploying to $TARGET (current: $CURRENT)"
# 1. Copy database from active to target
echo "Copying database..."
pg_dump -h pg-$CURRENT -U odoo odoo | psql -h pg-$TARGET -U odoo odoo_staging
# 2. Update code in target
echo "Updating code..."
docker compose -f docker-compose.$TARGET.yml pull
docker compose -f docker-compose.$TARGET.yml up -d
# 3. Run module upgrade on target
echo "Running module upgrade..."
docker compose -f docker-compose.$TARGET.yml exec odoo \
odoo -d odoo_staging -u your_modules --stop-after-init
# 4. Smoke test
echo "Running smoke tests..."
curl -f http://localhost:${TARGET_PORT}/web/health || {
echo "SMOKE TEST FAILED. Aborting."
exit 1
}
# 5. Switch traffic
echo "Switching traffic to $TARGET..."
sed -i "s/odoo-$CURRENT/odoo-$TARGET/g" /etc/nginx/conf.d/odoo.conf
nginx -s reload
# 6. Record active environment
echo $TARGET > /opt/deploy/active
echo "Deployment complete. $TARGET is now active."Step 3: Database Handling
The database is the trickiest part. Options:
| Strategy | Downtime | Data Loss Risk | Complexity |
|---|---|---|---|
| Shared database | Zero | None | Low (but migration risk) |
| Database copy before switch | Brief (pg_dump) | Transactions during copy | Medium |
| Logical replication | Zero | None | High |
| Point-in-time clone (ZFS/LVM) | Seconds | None | Medium |
Recommended: Shared Database with Migration Guard
For most Odoo deployments, sharing a single database between blue and green is simplest. The key is ensuring backward compatibility:
- New fields should have defaults so old code handles them
- Avoid removing columns in the same release that drops the code
- Test the migration on a database copy before switching
Step 4: Rollback
#!/bin/bash
# rollback.sh - Instant rollback
CURRENT=$(cat /opt/deploy/active)
if [ "$CURRENT" = "blue" ]; then
ROLLBACK="green"
else
ROLLBACK="blue"
fi
echo "Rolling back to $ROLLBACK..."
sed -i "s/odoo-$CURRENT/odoo-$ROLLBACK/g" /etc/nginx/conf.d/odoo.conf
nginx -s reload
echo $ROLLBACK > /opt/deploy/active
echo "Rollback complete. $ROLLBACK is now active."Step 5: Automated Health Checks
#!/bin/bash
# health_check.sh - Verify deployment health
TARGET_URL="http://odoo-$TARGET:8069"
# Check HTTP response
HTTP_CODE=$(curl -s -o /dev/null -w '%{http_code}' $TARGET_URL/web/health)
if [ "$HTTP_CODE" != "200" ]; then
echo "FAIL: HTTP health check returned $HTTP_CODE"
exit 1
fi
# Check response time
RESP_TIME=$(curl -s -o /dev/null -w '%{time_total}' $TARGET_URL/web/login)
if (( $(echo "$RESP_TIME > 5" | bc -l) )); then
echo "FAIL: Response time ${RESP_TIME}s exceeds 5s threshold"
exit 1
fi
# Check database connectivity
PG_STATUS=$(docker compose exec odoo python3 -c "import psycopg2; psycopg2.connect('...')" 2>&1)
if [ $? -ne 0 ]; then
echo "FAIL: Database connectivity check failed"
exit 1
fi
echo "All health checks passed"CI/CD Integration
Integrate blue-green deployment into your CI/CD pipeline:
- Push code to main branch
- CI builds new Docker image
- CI pushes image to registry
- CD triggers deployment script
- Script deploys to idle environment
- Automated tests run against new deployment
- If tests pass, switch traffic
- If tests fail, alert team, no traffic switch
DeployMonkey + Blue-Green
DeployMonkey supports blue-green deployment strategies for managed Odoo instances. Deploy updates with zero downtime and instant rollback capability through the control panel.