Both blue-green and canary deployments exist to solve the same underlying problem — releasing new code without a hard cutover that instantly exposes every user to a bad build — but they trade off risk exposure, infrastructure cost, and rollback speed in different ways. Picking between them isn't about which is "more modern"; it's about which failure mode you're more willing to accept.

Blue-green: instant cutover, instant rollback

Blue-green maintains two complete, identical production environments. At any time, one (say, blue) serves all live traffic while the other (green) sits idle or receives the new release. Once green is verified, traffic switches over entirely, usually at the load balancer or DNS level:

yaml
# Service selector flip is the actual cutover moment
apiVersion: v1
kind: Service
metadata:
  name: api
spec:
  selector:
    app: api
    version: green   # was "blue" a moment ago
  ports:
    - port: 80
      targetPort: 8080

The appeal is rollback speed: if green misbehaves, flipping the selector back to blue is immediate, with zero redeploy time, because blue never stopped running. The cost is that you're running two full production-sized environments simultaneously during every release, which roughly doubles compute spend for the deployment window and complicates anything stateful — database migrations in particular need to be backward-compatible with both versions until the cutover completes.

Canary: gradual exposure, gradual confidence

Canary releases route a small percentage of real traffic to the new version while the rest continues to the stable one, then ramp that percentage up as confidence builds, typically gated by error rate and latency metrics rather than a fixed timer:

yaml
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: api
spec:
  strategy:
    canary:
      steps:
        - setWeight: 10
        - pause: { duration: 10m }
        - setWeight: 50
        - pause: { duration: 10m }
        - setWeight: 100
      canaryService: api-canary
      stableService: api-stable

Argo Rollouts (or similar controllers for other platforms) can wire this to automated analysis — querying Prometheus for the canary's error rate at each step and aborting the rollout automatically if it exceeds a threshold, without a human needing to watch a dashboard in real time.

The trade-off is exposure time and complexity: a bad canary still affects some percentage of real users during the ramp-up window, and rollback isn't instantaneous — it means shifting weight back to zero, which can take a few minutes rather than one atomic switch. Canary also requires request-level routing granularity (a service mesh or ingress controller that supports weighted traffic splitting), which blue-green doesn't need at all.

When each one actually fits

Blue-green suits services where a bad deploy is catastrophic and needs to be reversible in seconds — payment processing, authentication — and where the infrastructure cost of running two full environments is acceptable. It's a poor fit for services with expensive-to-duplicate state, like a large stateful cache that would need to be warmed twice.

Canary suits high-traffic services where a statistically meaningful signal (error rate, latency percentiles) can be gathered from a small slice of traffic quickly, and where the team has invested in the traffic-splitting and automated-analysis tooling to make the ramp-up actually safer than a straight cutover, not just slower. For a low-traffic internal service, a 10% canary might see so few requests that a genuine regression doesn't show up as statistically significant until it's already at 100% weight — in that case, blue-green's clean binary switch is often the more honest safety mechanism.

Plenty of mature platforms run both: blue-green for a handful of critical, stateful services, canary for the high-volume stateless ones where gradual exposure actually earns its complexity.