Skip to content
Codeloom
DevOps

Blue-Green vs Canary Deployments Explained

Compare blue-green and canary deployment strategies with practical examples to choose the right zero-downtime release approach for your team.

·6 min read · By Codeloom
Intermediate 10 min read

What you'll learn

  • How blue-green deployments work end to end
  • How canary deployments shift traffic gradually
  • Trade-offs between the two strategies
  • Practical Kubernetes examples for both
  • When to use each approach

Prerequisites

None — this post is self-contained.

Shipping code to production without downtime is table stakes for modern teams. Two strategies dominate the conversation: blue-green deployments and canary deployments. Both eliminate the maintenance window, but they manage risk in fundamentally different ways. This article breaks down the mechanics, trade-offs, and practical implementation of each so you can make an informed choice.

Blue-Green Deployments

A blue-green deployment maintains two identical production environments. At any given time one environment (blue) serves all live traffic while the other (green) sits idle or runs the new version. When you are ready to release, you switch the router so that all traffic moves from blue to green in a single cut.

The beauty is simplicity. You deploy the new version to the idle environment, run your smoke tests against it, and flip the switch. If something is wrong, you flip back. Rollback is instant because the old environment is still running.

Kubernetes Example

You can implement blue-green with two Deployments and a Service selector. Start with the blue version serving traffic:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: api-blue
spec:
  replicas: 3
  selector:
    matchLabels:
      app: api
      slot: blue
  template:
    metadata:
      labels:
        app: api
        slot: blue
    spec:
      containers:
        - name: api
          image: myregistry/api:1.4.0
          ports:
            - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: api
spec:
  selector:
    app: api
    slot: blue          # points to blue
  ports:
    - port: 80
      targetPort: 8080

Deploy the green version alongside it:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: api-green
spec:
  replicas: 3
  selector:
    matchLabels:
      app: api
      slot: green
  template:
    metadata:
      labels:
        app: api
        slot: green
    spec:
      containers:
        - name: api
          image: myregistry/api:1.5.0
          ports:
            - containerPort: 8080

Once smoke tests pass against the green pods, switch the Service selector:

kubectl patch service api \
  -p '{"spec":{"selector":{"slot":"green"}}}'

All traffic now hits version 1.5.0. To roll back, patch the selector back to blue. After you gain confidence, scale down the blue Deployment.

Pros and Cons

Blue-green gives you instant rollback and a dead-simple mental model. The downside is cost: you need double the infrastructure during the transition window. It is also all-or-nothing. Every user gets the new version at the same moment, so a subtle bug affects 100 percent of traffic the instant you flip.

Canary Deployments

A canary deployment takes the opposite approach. Instead of switching all traffic at once, you route a small percentage to the new version and gradually increase it as metrics confirm the release is healthy.

The name comes from the coal mine canary: a small group of requests acts as the early warning system. If error rates, latency, or business metrics degrade, you halt the rollout and route everything back to the stable version.

Kubernetes Example with Ingress Weights

Many ingress controllers support traffic splitting with annotations. Here is an example using NGINX Ingress:

# Stable ingress - receives most traffic
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: api-stable
spec:
  rules:
    - host: api.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: api-stable
                port:
                  number: 80
---
# Canary ingress - receives a percentage
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: api-canary
  annotations:
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-weight: "10"
spec:
  rules:
    - host: api.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: api-canary
                port:
                  number: 80

Start at 10 percent. Monitor your dashboards. If everything looks good, bump the weight to 25, then 50, then 100. Each step is a chance to catch problems before they reach the full user base.

Automated Canary with Flagger

Flagger automates the weight progression and analysis. Define a Canary resource:

apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
  name: api
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: api
  service:
    port: 80
  analysis:
    interval: 1m
    threshold: 5
    maxWeight: 50
    stepWeight: 10
    metrics:
      - name: request-success-rate
        thresholdRange:
          min: 99
        interval: 1m
      - name: request-duration
        thresholdRange:
          max: 500
        interval: 1m

Flagger watches the success rate and latency. If both stay within thresholds, it increments the canary weight by 10 percent every minute until it reaches 50 percent, then promotes. If metrics breach the threshold five times, it rolls back automatically.

Comparing the Two Strategies

FactorBlue-GreenCanary
Blast radius100% on switchStarts small, grows
Rollback speedInstant (switch back)Fast (reset weight)
Infrastructure cost2x during deployMarginal overhead
ComplexityLowMedium to high
Best forStateless apps, small teamsHigh-traffic services, risk-averse orgs

Blue-green suits teams that want simplicity and can afford the extra capacity. Canary suits teams running high-traffic services where exposing a bug to every user at once is unacceptable.

Database Migrations

Neither strategy solves database schema changes automatically. Both require backward-compatible migrations. The rule is: the old version and the new version must be able to run against the same database schema simultaneously. Use expand-and-contract migrations. Add the new column first, deploy code that writes to both old and new columns, then drop the old column in a later release.

Choosing the Right Strategy

Start with blue-green if your service is small, your team is learning, or your deployments are infrequent. The cognitive overhead is minimal and the rollback story is excellent.

Move to canary when your service handles enough traffic that a bad deploy causes real damage, when you have monitoring mature enough to detect regressions automatically, or when you want to combine deployment with experimentation.

Many teams use both. Blue-green for internal services where the blast radius is contained. Canary for the public-facing API where a one percent error spike means thousands of failed requests.

Wrap-up

Blue-green and canary deployments both eliminate downtime, but they manage risk differently. Blue-green is simple and gives you an instant rollback switch. Canary is more nuanced and limits blast radius by shifting traffic gradually. Pick the one that matches your traffic volume, monitoring maturity, and risk tolerance, and remember that the best deployment strategy is the one your team actually understands and trusts.