✦ For everyone, free.

Practical knowledge for real and everyday life

Home

14.3.3 Blue Green Deployment

A focused guide to Blue Green Deployment, connecting core concepts with practical Docker and container operations.

Blue-green deployment is a release strategy that maintains two complete, independent production environments, conventionally labeled blue and green, where only one serves live traffic at any given time, and a new release is deployed entirely into the idle environment, validated there, and then promoted by switching traffic to it, leaving the previously active environment intact as an immediate rollback target.

The two environments

Both environments run the full application stack, identically configured except for the version of the application deployed into them. At any moment, one is live (receiving real traffic) and the other is idle (either stopped, or running the previous release as a standby):

docker compose -p myapp-blue -f docker-compose.yml up -d
docker compose -p myapp-green -f docker-compose.yml up -d

Using a distinct Compose project name for each environment, rather than a single shared project, keeps their containers, networks, and volumes entirely separate, which is what allows both to exist simultaneously without interfering with each other.

Deploying the new release into the idle environment

A new version is deployed by updating the idle environment's image reference and bringing it up, while the currently live environment remains completely untouched and continues serving production traffic throughout:

docker compose -p myapp-green -f docker-compose.yml -f docker-compose.production.yml \
  pull
docker compose -p myapp-green -f docker-compose.yml -f docker-compose.production.yml \
  up -d

Because the live environment is not modified at all during this step, there is zero risk to current production traffic from anything that happens while the new release is being deployed and validated in the idle environment.

Validating before switching traffic

Before any real traffic is routed to the newly deployed environment, it should be validated directly, through health checks, smoke tests, and ideally a brief period of synthetic or internal traffic:

curl -f http://green.internal:3000/healthz
docker compose -p myapp-green run --rm api npm run smoke-test

The idle environment being fully isolated from production traffic during this validation step is the core safety property of blue-green deployment: a problem discovered here has affected nothing that real users were depending on.

Switching traffic

The cutover itself is a routing change at the load balancer or reverse proxy layer, redirecting traffic from the currently live environment to the newly validated one:

upstream backend {
    server green.internal:3000;
}
docker exec proxy nginx -s reload

This switch is close to instantaneous from the proxy's perspective, since no containers need to start or stop as part of it; the only thing changing is which existing, already-running environment receives new connections.

Rollback as the mirror operation

If a problem surfaces after the switch, even one that passed validation but only manifests under real production load or data, rollback is simply reversing the same routing change, pointing traffic back at the previous environment, which was deliberately left running and untouched:

upstream backend {
    server blue.internal:3000;
}
docker exec proxy nginx -s reload

Because the previous environment was never stopped, rollback does not involve redeploying anything or waiting for containers to start; it is exactly as fast as the original cutover was, which is the main practical advantage blue-green deployment offers over patterns that replace containers in place.

Database and shared state considerations

Blue-green deployment is straightforward for stateless application tiers, but a single shared database used by both environments introduces a constraint: any schema change deployed alongside the new release must remain compatible with the previous release's code, since that previous release is still running, intact, in the other environment, ready to receive traffic again if a rollback is needed.

-- Safe: an additive, backward-compatible change
ALTER TABLE users ADD COLUMN display_name VARCHAR(255);
-- Risky for blue-green: removes something the standby environment's code still expects
ALTER TABLE users DROP COLUMN legacy_name;

This is the same backward-compatibility discipline relevant to any rolling deployment, but it applies with particular force in blue-green deployment, since the explicit promise of an instant rollback is only kept if the standby environment's code can still run correctly against whatever the database currently looks like.

Cost of running two full environments

The most direct cost of blue-green deployment is infrastructure: both environments need to be provisioned and capable of handling full production load, even though only one is actively serving traffic at any given moment, which roughly doubles the resource footprint during the period both environments exist side by side.

docker compose -p myapp-blue ps
docker compose -p myapp-green ps

For organizations where this cost is significant relative to the benefit, scaling the idle environment down to a minimal footprint between deployments, and scaling it up only during the deployment and validation window, is a common way to reduce the ongoing cost while keeping the pattern's core safety property intact.

Cleaning up after a successful cutover

Once a release has been live in the new environment for long enough to be confident no rollback will be needed, the previous environment can be torn down or repurposed as the idle environment for the next release:

docker compose -p myapp-blue down

The next deployment then targets this now-idle environment, and the roles of blue and green effectively swap with each release cycle.

Common mistakes

  • Sharing a single database between both environments without enforcing backward-compatible schema changes, undermining the instant-rollback guarantee blue-green deployment is meant to provide.
  • Switching traffic to the new environment without adequate validation, effectively turning blue-green deployment into a recreate deployment with extra infrastructure cost and no real safety benefit.
  • Tearing down the previous environment immediately after cutover, removing the rollback target before enough time has passed to be confident the new release is stable.
  • Underestimating the infrastructure cost of running two full environments and abandoning the pattern partway through implementation rather than planning for the cost upfront.
  • Forgetting that background jobs, scheduled tasks, or queue consumers running in both environments simultaneously can cause duplicate processing if not explicitly designed to handle that case.

Blue-green deployment trades roughly double the infrastructure cost during each deployment window for a release process that validates entirely outside of production traffic and can be rolled back as fast as the original cutover, making it most valuable for services where deployment risk and rollback speed matter more than the additional infrastructure spend required to support it.

Content in this section