Blue-Green Deployment
Two identical environments with instant traffic switching, database migration challenges, rollback in seconds, and DNS vs load balancer switching strategies for zero-downtime deployments.
What it is
Blue-green deployment is a release strategy that maintains two identical production environments — blue (current live) and green (new version) — and switches traffic between them in a single, near-instantaneous operation. At any time, only one environment is serving production traffic. The deployment process: (1) new version is deployed to the idle environment; (2) smoke tests and validation run against the idle environment; (3) the load balancer or DNS record is updated to route traffic to the new environment; (4) the old environment is kept live for a period to enable instant rollback; (5) after a stability window, the old environment is decommissioned or repurposed for the next release cycle.
The traffic switch can be performed at different layers. Load balancer switching is the most common: the load balancer's target group is changed from blue to green. This is near-instantaneous (under a second) and provides immediate rollback capability by reverting the target group assignment. DNS switching updates the DNS record to point to the new environment's IP or load balancer. DNS is slower due to TTL propagation (even with TTL set to 30-60 seconds, some clients cache longer) but works for environments without a shared load balancer. Kubernetes Service switching changes the Service selector labels to route to the new Deployment's pods — the cleanest approach in Kubernetes where both deployments coexist in the cluster and traffic switch is a label selector update.
Blue-green is distinct from rolling deployments (incrementally replacing pods one at a time) and canary releases (routing a small percentage to the new version). Blue-green performs a complete, simultaneous switch of all traffic — it is binary, not gradual. This means if the new version has a problem, all users are affected rather than a subset. The compensation is that rollback is trivially fast — reverting to blue takes the same time as the original switch, typically under a second.
Why it exists
Before zero-downtime deployment techniques, releasing new software required taking the service offline for maintenance windows — often scheduled at 3am Sunday. Blue-green deployment was one of the first systematic approaches to achieving zero-downtime deployments. It provides a clean separation between deployment (getting the new code running) and release (switching users to it), reducing deployment risk by allowing full validation of the new version in a production-identical environment before any user sees it. The instant rollback capability means the window of user impact from a bad deployment is seconds, not the minutes or hours required to redeploy the old version.
When to use
- Services with strict uptime requirements where rolling deployments with mixed-version periods are unacceptable.
- Database-heavy deployments where the new version requires schema migrations that must be applied before switching traffic.
- When fast, tested rollback is more important than gradual traffic exposure — e.g., critical payment processing services.
When not to use
- Cost-constrained environments where running two full production-scale environments doubles infrastructure costs for services with large compute requirements.
- When gradual exposure and metric-gated rollout is preferred over all-or-nothing switching — use canary releases instead.
Typical architecture
KUBERNETES BLUE-GREEN:
# Blue deployment (current live)
apiVersion: apps/v1
kind: Deployment
metadata:
name: checkout-blue
labels: { app: checkout, slot: blue, version: v1.2.0 }
spec:
replicas: 10
selector:
matchLabels: { app: checkout, slot: blue }
# Green deployment (new version - pre-switch)
apiVersion: apps/v1
kind: Deployment
metadata:
name: checkout-green
labels: { app: checkout, slot: green, version: v1.3.0 }
spec:
replicas: 10
selector:
matchLabels: { app: checkout, slot: green }
# Service (routes to active slot)
apiVersion: v1
kind: Service
metadata:
name: checkout
spec:
selector:
app: checkout
slot: blue # <-- change to 'green' to switch traffic
SWITCHING TRAFFIC (single kubectl command):
kubectl patch service checkout \
-p '{"spec":{"selector":{"slot":"green"}}}'
# Rollback is identical:
kubectl patch service checkout \
-p '{"spec":{"selector":{"slot":"blue"}}}'
AWS ALB BLUE-GREEN:
# Two target groups: checkout-blue, checkout-green
# ALB listener rule points to active target group
# Switch via AWS CLI (sub-second):
aws elbv2 modify-listener \
--listener-arn arn:aws:elasticloadbalancing:... \
--default-actions \
Type=forward,TargetGroupArn=arn:...:checkout-green
DATABASE MIGRATION STRATEGY:
Phase 1: Deploy Blue (v1.2) + Green (v1.3)
- Apply ADDITIVE schema changes only (new columns/tables)
- v1.3 must be compatible with old schema AND new schema
- v1.2 continues serving production
Phase 2: Switch traffic to Green (v1.3)
- All traffic now served by v1.3 with new application logic
- Database has both old and new columns
Phase 3: Cleanup (next release cycle)
- Remove backward compatibility code
- Drop old columns in a follow-up migration
Pros and cons
Pros
- Zero-downtime deployments: traffic switch is instantaneous with no request drops (for load balancer switching), eliminating maintenance windows entirely.
- Instant rollback: reverting to the previous version takes the same time as the original switch — seconds — rather than the minutes required to redeploy the old version.
- Full pre-production validation: the green environment can be thoroughly smoke-tested against production data and infrastructure before any user traffic is routed to it.
Cons
- Double infrastructure cost: running two full-scale production environments doubles compute costs during the deployment window; for large, expensive services this is significant.
- Database migrations are complex: additive-only migrations (expand-contract pattern) must be applied before the switch, requiring coordination between schema changes and application code across multiple release cycles.
- All-or-nothing exposure: unlike canary releases, all users are switched simultaneously — if a bug exists that wasn't caught in validation, all users are affected immediately.
Implementation notes
Database migration is the hardest part of blue-green deployment. The naive approach — running destructive migrations before the switch — means that if rollback is needed, the old application code may be incompatible with the new schema. The solution is the expand-contract (or parallel-change) pattern: migrations are split into three phases. Expand: add new columns/tables while keeping old ones; both old and new application versions work. Contract: after the new version is stable in production, remove the old columns/tables in a subsequent release. This requires careful coordination and discipline but makes rollback always safe.
In Kubernetes, use Argo Rollouts or Flagger rather than managing blue-green manually. These tools automate the deployment lifecycle: create the green deployment, run analysis (metric checks, smoke tests), switch the service selector, optionally scale down the blue deployment, and roll back automatically if analysis fails. This removes the operational complexity of coordinating the multi-step process manually.
Common failure modes
- Schema migration not applied before switch: Application code references new columns that don't exist yet; requests fail immediately after switch; rollback restores traffic but database state may be inconsistent.
- Insufficient green environment warmup: Green environment switches cold — connection pools not warmed, JVM not JIT-compiled, caches empty — causing latency spike or errors in the minutes after switch due to cold start behavior.
- Session state loss: If user sessions are stored in the application instance (not an external session store), switching environments invalidates all active sessions; users are logged out mid-session.
Decision checklist
- Can the environment cost (2x compute) be justified for the deployment window?
- Are database migrations using the expand-contract pattern for rollback safety?
- Is session state stored externally (Redis/database) so sessions survive environment switching?
- Is the green environment warmed up (connection pools, caches) before the traffic switch?
- Is there an automated smoke test suite that runs against the green environment before switching?
- Is the old environment kept running for a defined stability window before teardown?
Example use cases
- E-commerce checkout release: Payment processing service with zero downtime SLA; deploys new version to green, runs 10-minute automated test suite including transaction simulations, switches load balancer in 500ms; no customer impact; previous blue environment kept warm for 30 minutes; rolled back in 2 seconds when a post-switch metric anomaly is detected.
- Regulatory-required deployment window: Banking application required to complete deployments within a 30-second maintenance window per contract; blue-green achieves this by having green pre-deployed and validated before the window opens.
- A/B test infrastructure: Marketing team wants to serve different landing page versions; blue-green infrastructure extended with weighted routing to split traffic 50/50 between environments for conversion testing before full switch.
Related patterns
- Canary Releases — Gradual traffic shifting instead of all-or-nothing switching.
- Release Strategies — Comparison of rolling, recreate, blue-green, and canary strategies.
- Feature Flags — Alternative to environment-based switching for feature gating.