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:
- Creates a canary Deployment with the new version
- Starts sending a small percentage of traffic to the canary
- Measures metrics (success rate, latency, custom metrics)
- If metrics pass thresholds, increases traffic weight
- Continues until canary has 100% traffic (and becomes primary)
- 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
- Get Prometheus and Grafana running (you need metrics for analysis)
- Deploy Flagger or Argo Rollouts
- Configure your first Canary resource on a low-risk service
- Watch it in action—deploy a new version and observe the traffic shift
- Add custom business metrics to the analysis
- 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.