Progressive Delivery: Beyond Blue-Green and Canary Deployments

Progressive Delivery: Beyond Blue-Green and Canary Deployments

The problem with traditional deployments is binary: the new version is either deployed or it isn’t. The problem with canary deployments without automation is that someone has to be watching and deciding. Progressive delivery automates the graduation process: shift traffic gradually, measure what matters, roll forward if metrics look good, roll back if they don’t—without human intervention.

This isn’t just convenient. It’s the difference between “we deploy at 2am when traffic is low because deployments are scary” and “we deploy continuously because deployments are boring.”

The Progression from Traditional to Progressive

Big bang: Deploy all at once to all users. Roll back if something breaks. High blast radius, high risk.

Blue-green: Maintain two identical environments. Switch traffic from blue (current) to green (new) all at once. Easy rollback (switch back). Still high blast radius for the switch.

Canary: Deploy to a small subset of users first. If it looks good, deploy to everyone. Manual process unless automated.

Progressive delivery: Automated canary with metric-based promotion criteria. Traffic shifts gradually. The system promotes or rolls back based on measured outcomes, not human judgment.

Flagger: Automated Progressive Delivery

Flagger is a CNCF project that works with Kubernetes to automate progressive delivery. It integrates with service meshes (Istio, Linkerd), ingress controllers (NGINX, Traefik), and load testing tools (Vegeta, k6).

Flagger works by watching a Deployment. When you update the Deployment (change the image tag), Flagger takes over:

  1. Creates a canary Deployment with the new version
  2. Starts sending a small percentage of traffic to the canary
  3. Measures metrics (success rate, latency, custom metrics)
  4. If metrics pass thresholds, increases traffic weight
  5. Continues until canary has 100% traffic (and becomes primary)
  6. If metrics fail at any step, rolls back to previous version
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
  name: my-app
  namespace: my-app
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: my-app
  progressDeadlineSeconds: 600
  service:
    port: 80
    targetPort: 8080
  analysis:
    interval: 1m           # Check metrics every minute
    threshold: 5           # Max number of failed metric checks before rollback
    maxWeight: 50          # Max percentage of traffic to send to canary
    stepWeight: 10         # Increase canary traffic by 10% each step
    metrics:
      - name: request-success-rate
        # Built-in metric - Prometheus query provided by Flagger
        thresholdRange:
          min: 99          # At least 99% success rate
        interval: 1m
      - name: request-duration
        # p99 latency under 500ms
        thresholdRange:
          max: 500
        interval: 30s
    webhooks:
      - name: load-test
        url: http://flagger-loadtester/
        timeout: 5s
        metadata:
          cmd: "hey -z 1m -q 10 -c 2 http://my-app.my-app/api/health"

When you run kubectl set image deployment/my-app app=myapp:2.0.0, Flagger begins the canary analysis automatically. You watch it in Grafana; you don’t manually approve each step.

Argo Rollouts: Progressive Delivery Without a Service Mesh

If you’re not running a service mesh, Argo Rollouts provides progressive delivery using NGINX Ingress annotations for traffic management:

apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: my-app
  namespace: my-app
spec:
  replicas: 5
  strategy:
    canary:
      canaryService: my-app-canary
      stableService: my-app-stable
      trafficRouting:
        nginx:
          stableIngress: my-app-stable
      steps:
        - setWeight: 20
        - pause: {}          # Manual approval gate at 20%
        - setWeight: 40
        - pause: {duration: 10m}  # Auto-proceed after 10 minutes
        - setWeight: 60
        - pause: {duration: 10m}
        - setWeight: 80
        - pause: {duration: 10m}
      analysis:
        templates:
          - templateName: success-rate
        startingStep: 2
        args:
          - name: service-name
            value: my-app-canary

Argo Rollouts introduces Rollout as a drop-in replacement for Deployment. You can migrate existing Deployments to Rollouts without changing your application.

The pause: {} (no duration) requires manual promotion: kubectl argo rollouts promote my-app. This is useful when you want automation for the easy cases but human judgment at key points.

Custom Metrics for Analysis

Built-in success rate and latency metrics cover many cases. But progressive delivery becomes more powerful when you define business-level metrics:

apiVersion: flagger.app/v1beta1
kind: MetricTemplate
metadata:
  name: checkout-success-rate
  namespace: my-app
spec:
  provider:
    type: prometheus
    address: http://prometheus.monitoring.svc.cluster.local:9090
  query: |
    sum(
      rate(
        checkout_orders_total{
          status="success",
          app=""
        }[]
      )
    ) /
    sum(
      rate(
        checkout_orders_total{
          app=""
        }[]
      )
    ) * 100
# In the Canary spec
analysis:
  metrics:
    - name: checkout-success-rate
      templateRef:
        name: checkout-success-rate
        namespace: my-app
      thresholdRange:
        min: 99.5  # Checkout success rate must stay above 99.5%
      interval: 1m

Now your canary analysis isn’t just “does the HTTP layer work?” It’s “are checkouts completing successfully?” A deployment that degrades checkout success rate—even if HTTP responses are 200 OK—will be automatically rolled back.

Feature Flags: The Complement to Progressive Delivery

Progressive delivery manages traffic percentage to versions. Feature flags manage which features are enabled for which users—even within the same running version.

They complement each other:

  • Progressive delivery: Deploy v2 to 10% of traffic, measure, graduate
  • Feature flags: Within v2 users, show the new checkout UI to 50% (A/B test)

Tools: LaunchDarkly (commercial), Unleash (open source), Flagsmith (open source), or GrowthBook.

The pattern: new features ship behind a flag. The flag is off in production. Progressive delivery promotes the new version to 100%. Then the flag is enabled for a subset of users, measured, and gradually enabled for everyone. Rollback means disabling the flag—no deployment required.

Deployment Frequency as a Metric

The Accelerate research (DORA metrics) shows that high-performing engineering organizations deploy more frequently than low performers—often multiple times per day vs. monthly.

Progressive delivery is what makes frequent deployment safe. When every deployment is a canary that automatically rolls back on degradation, deploying 10 times a day is less risky than deploying once a month with a big-bang release.

The goal isn’t to deploy more because more is better. It’s to get feedback faster, keep changes smaller, and make each deployment a non-event. Progressive delivery is the technical foundation that enables that.

Implementation Order

  1. Get Prometheus and Grafana running (you need metrics for analysis)
  2. Deploy Flagger or Argo Rollouts
  3. Configure your first Canary resource on a low-risk service
  4. Watch it in action—deploy a new version and observe the traffic shift
  5. Add custom business metrics to the analysis
  6. Gradually expand to more services

The first time you watch a bad deployment automatically roll back because the error rate threshold was exceeded—without anyone having to make a decision or even be awake—you understand why this matters.

Share this post: LinkedIn Reddit WhatsApp Mastodon
Jesse Borden

Jesse Borden

Software Engineer with an interest in hands on learning

I have several years of professional Information Technology (IT) experience leading staff and projects within the Department of War (DOW). I have managed Service Desk, Web Application Development, and System Administration teams. My two greatest passions are learning and conti...