Explore plans starting at ₹699/mo →
DevOps

Blue-Green and Canary Deployment Strategies for Zero-Downtime Releases

S
ServerRaja
9 min read
#Nginx#DevOps#Best Practices#CI/CD#Microservices#Load Balancing#High Availability
Blue-Green and Canary Deployment Strategies for Zero-Downtime Releases

Why Deployment Strategy Matters

How you deploy code to production is just as important as the code itself. A bad deployment strategy means downtime during releases, difficult rollbacks, and risk of breaking production for all users. Blue-green and canary deployments solve these problems by allowing you to release new versions safely, verify them in production, and roll back instantly if something goes wrong.

ServerRaja cloud servers give you the infrastructure flexibility to implement these strategies without breaking the bank.

Blue-Green Deployments

How It Works

Blue-green deployment maintains two identical production environments. At any time, only one environment serves live traffic (the "blue" environment). When you deploy a new version, you deploy it to the idle "green" environment, test it thoroughly, and then switch the load balancer to route traffic to green. If something goes wrong, you switch back to blue instantly.

Implementation with Nginx

Configure Nginx as your traffic router:

# /etc/nginx/conf.d/upstream.conf
upstream blue {
    server 10.0.1.10:3000;
    server 10.0.1.11:3000;
}

upstream green { server 10.0.2.10:3000; server 10.0.2.11:3000; }

# Variable to control active environment map $uri $active_backend { default "blue"; }

server { listen 80; server_name app.example.com;

location / { proxy_pass http://$active_backend; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } } ```

Create a deployment script:

#!/bin/bash
# deploy-blue-green.sh

ACTIVE_FILE="/etc/nginx/active_env" ACTIVE=$(cat $ACTIVE_FILE 2>/dev/null || echo "blue")

if [ "$ACTIVE" = "blue" ]; then TARGET="green" TARGET_SERVERS="10.0.2.10,10.0.2.11" else TARGET="blue" TARGET_SERVERS="10.0.1.10,10.0.1.11" fi

echo "Currently active: $ACTIVE" echo "Deploying to: $TARGET"

# Deploy to target environment IFS=',' read -ra SERVERS <<< "$TARGET_SERVERS" for server in "${SERVERS[@]}"; do echo "Deploying to $server..." ssh deploy@$server "cd /var/www/app && git pull && npm ci --production && pm2 restart app" done

# Run health checks on target environment echo "Running health checks..." for server in "${SERVERS[@]}"; do HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" "http://$server:3000/health") if [ "$HTTP_CODE" != "200" ]; then echo "Health check failed on $server (HTTP $HTTP_CODE). Aborting." exit 1 fi done

# Switch traffic to target environment sudo sed -i "s/default "$ACTIVE"/default "$TARGET"/" /etc/nginx/conf.d/upstream.conf sudo nginx -t && sudo nginx -s reload echo "$TARGET" > $ACTIVE_FILE

echo "Deployment complete. Active environment: $TARGET" ```

Rollback

Rolling back is as simple as switching back to the previous environment:

# Instant rollback
sudo sed -i 's/default "green"/default "blue"/' /etc/nginx/conf.d/upstream.conf
sudo nginx -s reload
echo "blue" > /etc/nginx/active_env

Canary Deployments

How It Works

Canary deployments release the new version to a small subset of users first. If the canary performs well (no errors, acceptable latency), you gradually increase traffic until the new version handles all requests. This minimizes the blast radius of bugs.

Implementation with Nginx

Configure weighted upstreams for canary routing:

# Traffic splitting for canary deployment
upstream app_backend {
    # Production servers receive 90% of traffic
    server 10.0.1.10:3000 weight=9;
    server 10.0.1.11:3000 weight=9;

# Canary servers receive 10% of traffic server 10.0.2.10:3000 weight=1; } ```

For more granular control, use Nginx's split_clients module:

split_clients "$remote_addr" $backend {
    10%    canary_backend;
    *      production_backend;
}

upstream production_backend { server 10.0.1.10:3000; server 10.0.1.11:3000; }

upstream canary_backend { server 10.0.2.10:3000; }

server { listen 80; server_name app.example.com;

location / { proxy_pass http://$backend; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } } ```

Canary Deployment Script

Automate the gradual traffic increase:

#!/bin/bash
# canary-deploy.sh

STAGES=(10 25 50 75 100) CANARY_SERVER="10.0.2.10" MONITORING_DURATION=300 # 5 minutes per stage

# Deploy to canary server echo "Deploying new version to canary server..." ssh deploy@$CANARY_SERVER "cd /var/www/app && git pull && npm ci --production && pm2 restart app"

# Health check on canary HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" "http://$CANARY_SERVER:3000/health") if [ "$HTTP_CODE" != "200" ]; then echo "Canary health check failed. Aborting." exit 1 fi

for stage in "${STAGES[@]}"; do echo "Canary receiving $stage% of traffic"

# Update Nginx weights PROD_WEIGHT=$((100 - stage)) sudo sed -i "s/server 10.0.2.10:3000 weight=.*/server 10.0.2.10:3000 weight=$stage;/" /etc/nginx/conf.d/upstream.conf sudo nginx -t && sudo nginx -s reload

echo "Monitoring for $MONITORING_DURATION seconds..." sleep $MONITORING_DURATION

# Check error rates (simplified) ERROR_RATE=$(curl -s "http://localhost:9090/api/v1/query?query=rate(http_requests_total{status=~'5..'}[5m])" | jq '.data.result[0].value[1]' -r) if (( $(echo "$ERROR_RATE > 0.01" | bc -l) )); then echo "Error rate ($ERROR_RATE) exceeds threshold. Rolling back." sudo sed -i "s/server 10.0.2.10:3000 weight=.*/server 10.0.2.10:3000 weight=0;/" /etc/nginx/conf.d/upstream.conf sudo nginx -s reload exit 1 fi done

echo "Canary deployment successful. New version is now serving 100% of traffic." ```

Choosing the Right Strategy

  • **Blue-Green**: Best when you need instant rollback and can afford double the infrastructure. Ideal for scheduled releases.
  • **Canary**: Best for continuous delivery with lower infrastructure overhead. Catches issues early with real traffic.
  • **Rolling Updates**: Kubernetes default. Good for most workloads but slower rollback.

Monitor error rates, latency percentiles, and CPU during every deployment. Set up automated rollback triggers to catch problems before they affect all users.

Conclusion

Blue-green and canary deployments transform risky production releases into controlled, observable processes. Start with blue-green for its simplicity and instant rollback, then adopt canary deployments as your monitoring matures. ServerRaja cloud servers make it easy to run the duplicate infrastructure these strategies require.

Blue-Green & Canary Deployments | ServerRaja