• Skip to secondary menu
  • Skip to main content
  • Skip to primary sidebar
  • Home
  • Projects
  • Products
  • Themes
  • Tools
  • Request for Quote

Vengala Vinay

Having 9+ Years of Experience in Software Development

  • Home
  • WordPress
  • PHP
    • Codeigniter
  • Django
  • Magento
  • Selenium
  • Server
Home » Zero-Downtime Blue-Green Deployment Pipelines for Perl Applications on DigitalOcean

Zero-Downtime Blue-Green Deployment Pipelines for Perl Applications on DigitalOcean

Architectural Overview: Blue-Green for Perl on DigitalOcean

Implementing zero-downtime deployments for Perl applications, especially those with stateful components or complex dependencies, requires a robust strategy. Blue-Green deployment offers a proven path by maintaining two identical production environments: “Blue” (current live) and “Green” (new version). Traffic is switched from Blue to Green only after Green has been thoroughly validated. This post details a practical implementation on DigitalOcean using HAProxy for traffic management and a simple scripting approach for environment provisioning and deployment.

Prerequisites and Setup

Before diving into the deployment pipeline, ensure the following are in place:

  • A DigitalOcean account with sufficient Droplets and resources.
  • SSH access to your DigitalOcean account and a basic understanding of Droplet management.
  • Perl application code managed in a Git repository.
  • A mechanism for managing application dependencies (e.g., Carton, cpanm).
  • HAProxy installed and configured on a dedicated load balancer Droplet.
  • Basic familiarity with shell scripting.

Infrastructure Provisioning with `doctl`

We’ll leverage DigitalOcean’s command-line interface (`doctl`) to provision and manage Droplets. This allows for repeatable infrastructure setup. First, ensure `doctl` is installed and authenticated. You can find installation instructions on the DigitalOcean documentation. We’ll define our infrastructure in a shell script.

Droplet Configuration Script (`provision_infra.sh`)

This script will create the necessary Droplets for our Blue and Green environments, along with a load balancer. For simplicity, we’ll assume a single application server per environment. In a production scenario, you’d likely have multiple servers per environment behind HAProxy.

#!/bin/bash

# --- Configuration ---
REGION="nyc3"
SIZE="s-2vcpu-4gb" # Adjust as needed
IMAGE="ubuntu-22-04-x64"
SSH_KEY_FINGERPRINT="YOUR_SSH_KEY_FINGERPRINT" # Get from 'doctl compute ssh-key list'
APP_NAME="my-perl-app"
TAG_BLUE="env:blue"
TAG_GREEN="env:green"
TAG_LB="role:loadbalancer"
LB_IP="" # Will be populated after LB creation

# --- Create Load Balancer ---
echo "Creating HAProxy Load Balancer..."
LB_ID=$(doctl compute load-balancers create \
  --region $REGION \
  --size $SIZE \
  --name "${APP_NAME}-lb" \
  --tag $TAG_LB \
  --health-check '{"protocol":"tcp", "port":80, "path":"/"}' \
  --algorithm round_robin \
  --droplet-ids "" \
  --node-ports '[80,443]' \
  --tag-filter $TAG_BLUE \
  --tag-filter $TAG_GREEN \
  --format ID --no-header)

if [ -z "$LB_ID" ]; then
  echo "Error creating load balancer."
  exit 1
fi
echo "Load Balancer created with ID: $LB_ID"

# Wait for LB to be ready and get its IP
echo "Waiting for Load Balancer IP..."
sleep 60 # Give it some time to provision
LB_IP=$(doctl compute load-balancers get $LB_ID --format PublicIPv4 --no-header)
if [ -z "$LB_IP" ]; then
  echo "Error retrieving Load Balancer IP. Please check DigitalOcean console."
  exit 1
fi
echo "Load Balancer IP: $LB_IP"

# --- Create Blue Environment Droplets ---
echo "Creating Blue environment Droplets..."
doctl compute droplet create "${APP_NAME}-blue-1" \
  --region $REGION \
  --size $SIZE \
  --image $IMAGE \
  --ssh-keys $SSH_KEY_FINGERPRINT \
  --tag $TAG_BLUE \
  --wait

echo "Blue Droplet created."

# --- Create Green Environment Droplets ---
echo "Creating Green environment Droplets..."
doctl compute droplet create "${APP_NAME}-green-1" \
  --region $REGION \
  --size $SIZE \
  --image $IMAGE \
  --ssh-keys $SSH_KEY_FINGERPRINT \
  --tag $TAG_GREEN \
  --wait

echo "Green Droplet created."

echo "Infrastructure provisioning complete."
echo "Load Balancer IP: $LB_IP"
echo "Remember to configure HAProxy on the load balancer Droplet."

Note: Replace YOUR_SSH_KEY_FINGERPRINT with your actual SSH key fingerprint. You can obtain this by running doctl compute ssh-key list. The --tag-filter on the load balancer is crucial for dynamically associating Droplets. We’ll add Droplets to these tags during deployment.

HAProxy Configuration for Blue-Green

The HAProxy configuration is central to directing traffic. We’ll use two distinct backend server groups, one for “Blue” and one for “Green”. A frontend rule will initially direct all traffic to the “Blue” backend. A manual intervention (or an automated script) will be required to switch traffic.

HAProxy Configuration File (`/etc/haproxy/haproxy.cfg`)

global
    log /dev/log    local0
    log /dev/log    local1 notice
    chroot /var/lib/haproxy
    stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
    stats timeout 30s
    user haproxy
    group haproxy
    daemon

defaults
    log     global
    mode    http
    option  httplog
    option  dontlognull
    timeout connect 5000
    timeout client  50000
    timeout server  50000
    errorfile 400 /etc/haproxy/errors/400.http
    errorfile 403 /etc/haproxy/errors/403.http
    errorfile 408 /etc/haproxy/errors/408.http
    errorfile 500 /etc/haproxy/errors/500.http
    errorfile 502 /etc/haproxy/errors/502.http
    errorfile 503 /etc/haproxy/errors/503.http
    errorfile 504 /etc/haproxy/errors/504.http

frontend http_frontend
    bind *:80
    bind *:443 ssl crt /etc/ssl/private/your_domain.pem # Assuming you have SSL configured
    mode http
    default_backend blue_backend

backend blue_backend
    mode http
    balance roundrobin
    # Dynamically add/remove servers based on tags
    # This requires a script to update HAProxy config and reload

backend green_backend
    mode http
    balance roundrobin
    # Dynamically add/remove servers based on tags
    # This requires a script to update HAProxy config and reload

# Example of static configuration (will be managed by script)
# server blue1 192.168.1.10:80 check
# server green1 192.168.1.20:80 check

listen stats
    bind *:8404
    mode http
    stats enable
    stats uri /stats
    stats realm Haproxy\ Statistics
    stats auth admin:YourSecurePassword # CHANGE THIS
    stats admin if TRUE

The key here is that the backend sections are initially empty or commented out. A separate script will be responsible for fetching Droplet IPs tagged with env:blue and env:green and dynamically updating the HAProxy configuration. After updating, HAProxy must be reloaded:

sudo systemctl reload haproxy

Deployment Pipeline Script

This script orchestrates the deployment process. It clones the application, installs dependencies, deploys to the “Green” environment, tests it, and then switches traffic.

Deployment Script (`deploy.sh`)

#!/bin/bash

# --- Configuration ---
APP_REPO="[email protected]:your_org/your_perl_app.git"
APP_DIR="/opt/your_perl_app"
DEPLOY_USER="deploy" # User on application Droplets
SSH_USER="root" # SSH user for Droplets
DIGITALOCEAN_TAG_BLUE="env:blue"
DIGITALOCEAN_TAG_GREEN="env:green"
APP_PORT="8080" # Port your Perl app listens on
HEALTH_CHECK_URL="/health" # URL for health checks

# --- Functions ---

# Get Droplet IPs by tag
get_droplet_ips() {
    local tag=$1
    doctl compute droplet list --tag $tag --format PublicIPv4 --no-header | tr '\n' ' '
}

# Update HAProxy configuration with current active servers
update_haproxy() {
    local blue_ips=$(get_droplet_ips $DIGITALOCEAN_TAG_BLUE)
    local green_ips=$(get_droplet_ips $DIGITALOCEAN_TAG_GREEN)

    # Construct backend server lines
    local blue_servers=""
    for ip in $blue_ips; do
        blue_servers+="server blue_app_${ip//./_} $ip:$APP_PORT check\n"
    done

    local green_servers=""
    for ip in $green_ips; do
        green_servers+="server green_app_${ip//./_} $ip:$APP_PORT check\n"
    done

    # Create a temporary HAProxy config
    # This is a simplified example. In production, you'd likely use a template
    # and manage the full config file more robustly.
    cat << EOF > /tmp/haproxy.cfg
global
    log /dev/log    local0
    log /dev/log    local1 notice
    chroot /var/lib/haproxy
    stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
    stats timeout 30s
    user haproxy
    group haproxy
    daemon

defaults
    log     global
    mode    http
    option  httplog
    option  dontlognull
    timeout connect 5000
    timeout client  50000
    timeout server  50000
    errorfile 400 /etc/haproxy/errors/400.http
    errorfile 403 /etc/haproxy/errors/403.http
    errorfile 408 /etc/haproxy/errors/408.http
    errorfile 500 /etc/haproxy/errors/500.http
    errorfile 502 /etc/haproxy/errors/502.http
    errorfile 503 /etc/haproxy/errors/503.http
    errorfile 504 /etc/haproxy/errors/504.http

frontend http_frontend
    bind *:80
    bind *:443 ssl crt /etc/ssl/private/your_domain.pem
    mode http
    acl is_green hdr(Host) -i green.your_domain.com # Example for testing Green directly
    use_backend green_backend if is_green
    default_backend blue_backend

backend blue_backend
    mode http
    balance roundrobin
$blue_servers

backend green_backend
    mode http
    balance roundrobin
$green_servers

listen stats
    bind *:8404
    mode http
    stats enable
    stats uri /stats
    stats realm Haproxy\ Statistics
    stats auth admin:YourSecurePassword
    stats admin if TRUE
EOF

    # Validate and replace HAProxy config
    if haproxy -c -f /tmp/haproxy.cfg; then
        sudo mv /tmp/haproxy.cfg /etc/haproxy/haproxy.cfg
        sudo systemctl reload haproxy
        echo "HAProxy configuration updated and reloaded."
    else
        echo "HAProxy configuration validation failed. Aborting."
        exit 1
    fi
}

# Deploy application to a specific environment (blue or green)
deploy_to_environment() {
    local env_tag=$1
    local env_name=$2 # e.g., "Blue" or "Green"

    echo "Deploying to $env_name environment ($env_tag)..."

    # Get IPs for the target environment
    local target_ips=$(get_droplet_ips $env_tag)
    if [ -z "$target_ips" ]; then
        echo "No Droplets found for tag $env_tag. Skipping deployment to $env_name."
        return 1
    fi

    # Add Droplets to the load balancer's target pools
    # This step is crucial for HAProxy to see the servers.
    # The exact command depends on how your LB is configured.
    # For DigitalOcean Load Balancers, this is managed via tags.
    # We assume the LB is already configured to watch these tags.

    # Deploy code and dependencies
    for ip in $target_ips; do
        echo "Deploying to $ip..."
        ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null $SSH_USER@$ip << EOF
            set -e # Exit immediately if a command exits with a non-zero status.

            # Ensure deploy user exists and has sudo privileges
            if ! id "$DEPLOY_USER" &>/dev/null; then
                sudo useradd -m -s /bin/bash $DEPLOY_USER
                echo "$DEPLOY_USER ALL=(ALL) NOPASSWD:ALL" | sudo tee /etc/sudoers.d/$DEPLOY_USER
                sudo chmod 0440 /etc/sudoers.d/$DEPLOY_USER
            fi

            # Clone or pull latest code
            if [ -d "$APP_DIR" ]; then
                echo "Pulling latest code..."
                sudo -u $DEPLOY_USER git -C $APP_DIR pull origin main # Assuming 'main' is your deployment branch
            else
                echo "Cloning repository..."
                sudo -u $DEPLOY_USER git clone $APP_REPO $APP_DIR
                sudo -u $DEPLOY_USER git -C $APP_DIR checkout main # Or your deployment branch
            fi

            # Install dependencies (using Carton as an example)
            echo "Installing dependencies..."
            cd $APP_DIR
            sudo -u $DEPLOY_USER carton install --deployment

            # Restart application server (e.g., Starman, Plackup)
            # This command will vary based on your application's setup.
            # Example for Starman:
            echo "Restarting application server..."
            sudo pkill -f 'starman --workers' # Graceful shutdown if possible
            sleep 2
            sudo -u $DEPLOY_USER starman --workers 4 --listen "*:$APP_PORT" --pid /var/run/your_app.pid app.psgi &
            sleep 5 # Give it time to start
            echo "Application restarted on $ip:$APP_PORT"
EOF
        if [ $? -ne 0 ]; then
            echo "Deployment to $ip failed."
            return 1
        fi
    done
    return 0
}

# Health check function
health_check() {
    local target_ip=$1
    local url=$2
    local retries=5
    local delay=10

    echo "Performing health check on $target_ip$url..."
    for i in $(seq 1 $retries); do
        if curl -s --head "$target_ip$url" | grep "200 OK" > /dev/null; then
            echo "Health check passed for $target_ip."
            return 0
        fi
        echo "Health check attempt $i/$retries failed for $target_ip. Retrying in $delay seconds..."
        sleep $delay
    done
    echo "Health check failed for $target_ip after $retries attempts."
    return 1
}

# --- Main Deployment Logic ---

echo "Starting Blue-Green Deployment..."

# 1. Provision/Update Infrastructure (if needed)
#    In a real CI/CD, this might be a separate step or triggered by changes.
#    For this script, we assume infra exists or is managed separately.
#    We will update HAProxy config to reflect current Droplets.

# 2. Update HAProxy to point to Blue (should already be there)
echo "Ensuring HAProxy points to Blue..."
update_haproxy # This will re-register existing blue servers

# 3. Deploy the new version to the Green environment
if ! deploy_to_environment $DIGITALOCEAN_TAG_GREEN "Green"; then
    echo "Deployment to Green environment failed. Aborting."
    exit 1
fi

# 4. Health Check the Green environment
echo "Performing health checks on Green environment..."
GREEN_IPS=$(get_droplet_ips $DIGITALOCEAN_TAG_GREEN)
ALL_GREEN_HEALTHY=true
for ip in $GREEN_IPS; do
    if ! health_check "http://$ip:$APP_PORT" $HEALTH_CHECK_URL; then
        ALL_GREEN_HEALTHY=false
        echo "One or more Green servers failed health checks. Manual intervention required."
        # In a real scenario, you might rollback or alert here.
        # For now, we'll proceed but flag the issue.
    fi
done

if [ "$ALL_GREEN_HEALTHY" = false ]; then
    echo "WARNING: Some Green servers failed health checks. Proceeding with caution."
    # Consider adding a manual confirmation step here.
fi

# 5. Switch traffic to Green
echo "Switching traffic to Green environment..."
# This is the critical step. We update HAProxy to route to the Green backend.
# We'll temporarily disable the blue backend and enable the green one.
# A more sophisticated approach might involve a specific "maintenance" page
# or a gradual rollout.

# Temporarily remove blue servers from HAProxy config
echo "Temporarily disabling Blue backend..."
BLUE_SERVERS_TO_REMOVE=$(get_droplet_ips $DIGITALOCEAN_TAG_BLUE)
if [ -n "$BLUE_SERVERS_TO_REMOVE" ]; then
    # This is a simplified approach. A robust solution would parse the existing config.
    # For now, we'll regenerate the config with *only* green servers.
    # This assumes the LB is configured to dynamically add/remove based on tags.
    # If not, we need to explicitly remove blue servers.
    # For DigitalOcean LB, this is handled by removing the 'env:blue' tag from the LB.
    # However, we are managing HAProxy directly on a DO Droplet here.
    # So, we need to modify the HAProxy config.

    # Let's re-generate the config, but this time, we'll comment out the blue backend
    # and make the green backend the default.
    # This requires modifying the update_haproxy function or creating a new one.

    # --- Simplified Traffic Switch ---
    # For this script, we'll assume HAProxy is configured to route to 'green_backend'
    # when 'blue_backend' is empty or unhealthy. A more direct switch involves
    # modifying the frontend rules or backend server lists.

    # A more direct switch: Modify frontend to point to green, or remove blue servers.
    # Let's simulate removing blue servers from the config.
    echo "Removing Blue servers from HAProxy config..."
    # This requires a more advanced config manipulation.
    # For simplicity, let's assume we can reload HAProxy with a config that
    # prioritizes Green or has Blue servers commented out.

    # A common pattern is to have a 'maintenance' backend or a specific frontend rule.
    # For this example, we'll simulate by reloading HAProxy with a config that
    # effectively switches. The `update_haproxy` function needs to be smarter.

    # Let's create a specific function for switching
    switch_to_green() {
        echo "Switching traffic to Green backend..."
        local green_ips=$(get_droplet_ips $DIGITALOCEAN_TAG_GREEN)
        local green_servers=""
        for ip in $green_ips; do
            green_servers+="server green_app_${ip//./_} $ip:$APP_PORT check\n"
        done

        # Create a temporary HAProxy config with ONLY green servers active
        cat << EOF > /tmp/haproxy_green.cfg
global
    log /dev/log    local0
    log /dev/log    local1 notice
    chroot /var/lib/haproxy
    stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
    stats timeout 30s
    user haproxy
    group haproxy
    daemon

defaults
    log     global
    mode    http
    option  httplog
    option  dontlognull
    timeout connect 5000
    timeout client  50000
    timeout server  50000
    errorfile 400 /etc/haproxy/errors/400.http
    errorfile 403 /etc/haproxy/errors/403.http
    errorfile 408 /etc/haproxy/errors/408.http
    errorfile 500 /etc/haproxy/errors/500.http
    errorfile 502 /etc/haproxy/errors/502.http
    errorfile 503 /etc/haproxy/errors/503.http
    errorfile 504 /etc/haproxy/errors/504.http

frontend http_frontend
    bind *:80
    bind *:443 ssl crt /etc/ssl/private/your_domain.pem
    mode http
    default_backend green_backend # Traffic now goes to Green

backend blue_backend # This backend is now empty
    mode http
    balance roundrobin

backend green_backend
    mode http
    balance roundrobin
$green_servers

listen stats
    bind *:8404
    mode http
    stats enable
    stats uri /stats
    stats realm Haproxy\ Statistics
    stats auth admin:YourSecurePassword
    stats admin if TRUE
EOF
        if haproxy -c -f /tmp/haproxy_green.cfg; then
            sudo mv /tmp/haproxy_green.cfg /etc/haproxy/haproxy.cfg
            sudo systemctl reload haproxy
            echo "HAProxy switched to Green backend."
        else
            echo "HAProxy configuration validation failed during switch. Aborting."
            exit 1
        fi
    }
    switch_to_green
fi

# 6. Post-deployment validation (optional but recommended)
echo "Performing final validation on Green environment..."
GREEN_IPS=$(get_droplet_ips $DIGITALOCEAN_TAG_GREEN)
ALL_GREEN_FINAL_HEALTHY=true
for ip in $GREEN_IPS; do
    if ! health_check "http://$ip:$APP_PORT" $HEALTH_CHECK_URL; then
        ALL_GREEN_FINAL_HEALTHY=false
        echo "Final health check failed for $ip."
    fi
done

if [ "$ALL_GREEN_FINAL_HEALTHY" = false ]; then
    echo "CRITICAL: Final health checks failed after traffic switch. Manual rollback required!"
    # Implement rollback logic here: switch traffic back to Blue.
    exit 1
fi

echo "Deployment to Green environment successful and traffic switched!"

# 7. Cleanup Blue environment (optional, can be done later)
echo "Blue environment is now idle. Consider decommissioning or preparing for next deployment."
# You might want to keep it running for a rollback window.

echo "Deployment pipeline finished."

Explanation of the Deployment Script:

  • `get_droplet_ips`: Fetches the public IPs of Droplets tagged with a specific environment (e.g., env:blue).
  • `update_haproxy`: This function is crucial. It dynamically generates an HAProxy configuration file based on the current IPs of Blue and Green Droplets. It then validates and reloads HAProxy. In a real-world scenario, you’d likely use a templating engine (like Jinja2) and manage the HAProxy configuration more formally.
  • `deploy_to_environment`: Iterates through the Droplets of the target environment (initially Green). For each Droplet, it SSHes in, pulls the latest code, installs dependencies (using Carton as an example), and restarts the application server.
  • `health_check`: A simple utility to poll a health check endpoint on a given server.
  • Main Logic:
    1. Ensures HAProxy is configured for Blue (initial state).
    2. Deploys the new version to the Green environment.
    3. Performs health checks on the Green servers.
    4. Switches Traffic: This is the core of the zero-downtime. The script simulates switching by reloading HAProxy with a configuration that directs all traffic to the Green backend. The `switch_to_green` function demonstrates this by creating a new config with only Green servers active.
    5. Performs final validation on the Green environment.
    6. Marks the Blue environment as idle.

Automating the Pipeline

This deployment script can be integrated into a CI/CD platform like GitLab CI, GitHub Actions, Jenkins, or a custom solution. The trigger could be a Git push to the main branch, a tag creation, or a manual trigger.

Example: GitHub Actions Workflow (`.github/workflows/deploy.yml`)

name: Deploy Perl App

on:
  push:
    branches:
      - main # Or your deployment branch

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v3

      - name: Set up SSH
        uses: webfactory/[email protected]
        with:
          ssh-private-key: ${{ secrets.DIGITALOCEAN_SSH_PRIVATE_KEY }}

      - name: Configure doctl
        uses: digitalocean/action-doctl@v2
        with:
          token: ${{ secrets.DIGITALOCEAN_TOKEN }}

      - name: Run Deployment Script
        env:
          APP_REPO: [email protected]:${{ github.repository }}.git # Adjust if repo is different
          APP_DIR: /opt/your_perl_app
          DEPLOY_USER: deploy
          SSH_USER: root
          DIGITALOCEAN_TAG_BLUE: env:blue
          DIGITALOCEAN_TAG_GREEN: env:green
          APP_PORT: 8080
          HEALTH_CHECK_URL: /health
          # Ensure your DigitalOcean Droplets have the correct SSH key associated
          # and that the SSH_USER has passwordless sudo access for the deploy user.
        run: |
          # Download the deploy.sh script or include it directly
          wget https://raw.githubusercontent.com/your_user/your_repo/main/deploy.sh -O deploy.sh
          chmod +x deploy.sh
          ./deploy.sh

Secrets Required for GitHub Actions:

  • DIGITALOCEAN_TOKEN: Your DigitalOcean API token with read/write permissions.
  • DIGITALOCEAN_SSH_PRIVATE_KEY: The private SSH key corresponding to the public key added to your DigitalOcean account and Droplets.

Rollback Strategy

In case of critical failures after the traffic switch, a rollback is essential. The simplest rollback is to switch traffic back to the Blue environment. This can be achieved by re-running a modified version of the `switch_to_green` function, but configured to point back to the Blue backend.

Rollback Script Snippet (`rollback.sh`)

#!/bin/bash

# ... (similar setup as deploy.sh) ...

# --- Rollback Function ---
switch_to_blue() {
    echo "Switching traffic back to Blue backend..."
    local blue_ips=$(get_droplet_ips $DIGITALOCEAN_TAG_BLUE)
    local blue_servers=""
    for ip in $blue_ips; do
        blue_servers+="server blue_app_${ip//./_} $ip:$APP_PORT check\n"
    done

    # Create a temporary HAProxy config with ONLY blue servers active
    cat << EOF > /tmp/haproxy_blue.cfg
global
    log /dev/log    local0
    log /dev/log    local1 notice
    chroot /var/lib/haproxy
    stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
    stats timeout 30s
    user haproxy
    group haproxy
    daemon

defaults
    log     global
    mode    http
    option  httplog
    option  dontlognull
    timeout connect 5000
    timeout client  50000
    timeout server  50000
    errorfile 400 /etc/haproxy/errors/400.http
    errorfile 403 /etc/haproxy/errors/403.http
    errorfile 408 /etc/haproxy/errors/408.http
    errorfile 500 /etc/haproxy/errors/500.http
    errorfile 502 /etc/haproxy/errors/502.http
    errorfile 503 /etc/haproxy/errors/503.http
    errorfile 504 /etc/haproxy/errors/504.http

frontend http_frontend
    bind *:80
    bind *:443 ssl crt /etc/ssl/private/your_domain.pem
    mode http
    default_backend blue_backend # Traffic now goes to Blue

backend blue_backend
    mode http
    balance roundrobin
$blue_servers

backend green_backend # This backend is now empty
    mode http
    balance roundrobin

listen stats
    bind *:8404
    mode http
    stats enable
    stats uri /stats
    stats realm Haproxy\ Statistics
    stats auth admin:YourSecurePassword
    stats admin if TRUE
EOF
    if haproxy -c -f /tmp/haproxy_blue.cfg; then
        sudo mv /tmp/haproxy_blue.cfg /etc/haproxy/haproxy.cfg
        sudo systemctl reload haproxy
        echo "HAProxy switched back to Blue backend."
    else
        echo "HAProxy configuration validation failed during rollback. Manual intervention required!"
        exit 1
    fi
}

# Execute rollback
switch_to_blue

echo "Rollback complete. Traffic is now directed to the Blue environment."

This rollback script can be triggered manually or automatically by monitoring tools that detect failures in the Green environment post-deployment.

Considerations for Stateful Applications

If your Perl application is stateful (e.g., relies on in-memory session data, local caches, or database connections that require specific handling), Blue-Green deployments become more complex. Strategies include:

  • Shared State Storage: Use external services like Redis, Memcached, or a robust database for session management and caching, accessible by both Blue and Green environments.
  • Database Migrations: Ensure database schema changes are backward-compatible. Deploy the new application code that can read both old and new schema versions, then perform schema migrations, and finally deploy the application version that requires the new schema. This is often referred to as “Expand/Contract” pattern for database changes.
  • Graceful Shutdown: Ensure your application server (e.g., Starman, Plackup) handles `SIGTERM` gracefully, finishing in-flight requests before exiting. This minimizes disruption during the traffic switch.

Conclusion

Implementing zero-downtime Blue-Green deployments for Perl applications on DigitalOcean is achievable with careful planning and automation. By leveraging tools like doctl for infrastructure, HAProxy for traffic management, and robust scripting for the deployment process, you can significantly reduce deployment risks and improve application availability. Remember to tailor the scripts to your specific application’s needs, dependency management, and operational requirements.

Primary Sidebar

A little about the Author

Having 9+ Years of Experience in Software Development.
Expertised in Php Development, WordPress Custom Theme Development (From scratch using underscores or Genesis Framework or using any blank theme or Premium Theme), Custom Plugin Development. Hands on Experience on 3rd Party Php Extension like Chilkat, nSoftware.

Recent Posts

  • Step-by-Step: Diagnosing thread pools deadlock during concurrent ActiveRecord transaction processing on Linode Servers
  • Securing Your E-commerce APIs: Preventing SQL Injection (SQLi) in customized checkout queries in WooCommerce Implementations
  • Disaster Recovery 101: Architecting Auto-Failovers for MySQL and Ruby Deployments on Linode
  • High-Throughput Caching Strategies: Scaling MySQL for Perl Application APIs
  • Disaster Recovery 101: Architecting Auto-Failovers for DynamoDB and Laravel Deployments on DigitalOcean

Copyright © 2026 · Vinay Vengala