Home/Blog/Canary Deployments vs. Feature Flags: A Framework for Platform Teams
Frameworks

Canary Deployments vs. Feature Flags: A Framework for Platform Teams

Every few weeks a platform engineer asks in some Slack somewhere: canary or feature flags? The answers are always confident and usually wrong, because the question is not either-or. The two mechanisms solve different failure modes. Getting the framework right saves a quarter of release engineering effort. Getting it wrong produces a stack that looks impressive on paper and fails at 25%.

What is the actual difference between canary and feature flags?

The confusion comes from both mechanisms exposing a subset of traffic to a new thing. But the thing is different.

  • Canary deployment. A new build artifact runs alongside the old one. A percentage of traffic (routed by the load balancer, service mesh, or deploy pipeline) hits the new build. The unit of change is the deployable artifact.
  • Feature flag. One build is running. Inside the code, a conditional checks the flag and takes one path or another. The unit of change is a config toggle.

The consequence: canary rolls out at the shape of your deploy pipeline (blue-green pods, container versions, service instances). Feature flags roll out at the shape of your code (per user, per team, per plan tier). Neither is more correct. They fit different risk profiles.

When should you use canary deployment?

When the risk is in the artifact, not the code path. Concrete cases:

  • Runtime or platform upgrades. New Node.js major, new JVM, new Kubernetes version. The old code should behave identically. If it does not, the problem is the platform, and only running the platform can tell you.
  • Dependency upgrades. A library bump. A driver change. A framework major.
  • Infrastructure migrations. New database driver. New object store client. Region change.
  • Performance-critical rewrites where the whole service was rebuilt. Rare, but real.

For all of these, wrapping the change in a feature flag inside the old build tests the wrong thing. You need the new artifact in production against real traffic.

When should you use feature flags?

When the risk is in the code path, not the artifact. Concrete cases:

  • User-facing feature rollouts. A new pricing page. A rewritten onboarding flow. A different checkout.
  • Behavior changes on existing endpoints. New algorithm for search ranking. New logic for tax calculation. New rate-limiting policy.
  • Kill switches. Anything you might want to turn off in seconds without a redeploy.
  • Per-user or per-tier experiences. Beta features, plan-gated features, entitlements.

Flag rollouts are cheaper and faster than canary because they do not require a deploy for every ramp change. They are also more precise because they can target by user ID rather than by traffic percentage.

When should you use both together?

When a single change carries both artifact risk and code path risk. This is more common than teams admit.

  • A checkout rewrite ships as a new build (canary risk) and gates the new flow behind a flag (code path risk).
  • A database driver upgrade ships as a new build (canary risk) and enables the new connection-pool behavior behind a flag (code path risk).
  • A rendering library swap ships as a new build (canary risk) and enables new component templates behind flags (code path risk).

For these, canary the deploy, then flag the feature within the canaried build. Advance both in coordinated cohorts. The alternative (canary alone) exposes 100% of the canary users to an unproven flow. The alternative (flag alone) means you cannot test the new build at all until it is fully deployed.

What are the trade-offs at a glance?

A working decision table:

Dimension Canary deployment Feature flags Both
Unit of change Build artifact Code path Both
Speed of ramp change Minutes (deploy) Seconds (config) Seconds
Rollback speed Seconds to minutes Under 30 seconds Under 30 seconds
Per-user targeting No (traffic percentage) Yes (user ID, plan, geo) Yes
Tests artifact risk Yes No Yes
Tests code path risk Partial (new build runs) Yes Yes
Overhead Deploy pipeline complexity Flag hygiene, code branches Both
Best for Platform upgrades Feature rollouts Mixed changes

Neither column is universally better. The last row is the one that matters: choose based on what kind of risk you are actually holding.

Where do both approaches fail without guardrails?

The failure mode is the same in both cases: you have exposed a subset of traffic to a new thing, but nothing is watching the subset.

  • A canary at 5% throws a subtle memory leak that only shows up under peak load 20 minutes in. The dashboard averages hide it because 95% of traffic is fine.
  • A flag ramp at 25% breaks a checkout code path only for users on a specific plan tier. Global conversion barely moves because that plan is 8% of revenue.

Both scenarios have the same fix: cohort-aware guardrails on top of whichever exposure mechanism you chose. Compare the treatment cohort against a matched control on error rate, latency, and the business metric the change could break. Halt or roll back automatically when the delta crosses a sequential test bound. This is the layer neither the canary tool nor the flag vendor provides natively for most teams, and it is where actual release safety lives.

How does progressive delivery relate to all of this?

Progressive delivery is the discipline of exposing changes in stages with guardrails at each stage. It is exposure-mechanism agnostic. You can do it with canary, with flags, or with both. It is not the tool; it is what you do with the tool.

A team practicing progressive delivery well looks the same regardless of stack:

  • Predefined ramp schedule (1%, 5%, 25%, 50%, 100%).
  • Guardrails on cohort vs. control for error rate, p95 latency, and one to three business metrics.
  • Sequential statistical tests, not raw threshold crossings.
  • Automatic halt or rollback on breach.
  • Evidence to Slack with the specific cohort, metric, and delta.

If your team has all five, the choice of canary vs. flags is a plumbing decision, not a safety decision.

What order should you introduce these in?

Most teams roll this out in stages. A defensible order:

  1. Deploy safety. A deploy pipeline that can canary artifact changes. This is table stakes and probably already exists.
  2. Flag hygiene. A flag vendor (or in-house system) with per-user targeting, cohort membership queries, and a hard rule that flags get deleted within 30 days of hitting 100%.
  3. Cohort-aware metrics. The ability to compute error rate, latency, and business metrics per cohort. This is the piece most teams underinvest in.
  4. Automatic guardrails. A decision engine that acts on cohort deltas. This is the payoff layer.

Skipping any step compounds risk downstream. Adding guardrails on top of a chaotic flag system fires false halts every day and gets turned off. Adding cohort metrics without a flag system to define cohorts is a research project. Do them in order.

The mistake to avoid

Framing canary vs. flags as a religious debate. Both exist because both address a specific kind of risk, and mature platform teams run both because their releases carry both kinds of risk. The question is not which mechanism you pick; it is whether the mechanism you pick is being watched. Exposure without observation is theater. Cohort-aware guardrails are what turn either mechanism into actual release safety, and they belong above both, not inside either.

canary deploymentfeature flagsrelease engineeringprogressive deliveryplatform engineering

Frequently asked questions

Can we replace canary deploys with feature flags entirely?

For code changes gated behind a flag, yes: the flag is a canary you can adjust without redeploying. For infra changes (a new Kubernetes version, an upgraded database driver, a JVM bump), no: the risk is in the build itself, and a flag inside the old build cannot test the new build. Most mature platform teams use flags for feature rollouts and keep canary in the deploy pipeline for artifact-level risk.

What is progressive delivery in relation to canary and flags?

Progressive delivery is the umbrella process: gradually expose a change to increasing cohorts with guardrails at each stage. It is agnostic to whether the exposure mechanism is a canary deploy, a feature flag, or both. Progressive delivery is the discipline; canary and flags are two ways to implement it. The guardrail layer is what makes any of it safe.

Do canary deployments still make sense with modern service meshes?

Yes, and service meshes make them cheaper. Istio, Linkerd, and Cilium can route a percentage of traffic to a new pod set without touching your application code. That is a real advantage over flag-based rollouts when the change is stateless and lives at the request-routing layer. For anything that needs per-user consistency (feature availability tied to a user ID), you still need flags.

Which approach is safer for database migrations?

Neither is safe alone. Migrations need a specific playbook: dual-write, dual-read, backfill, verify, cut over. Feature flags help gate the dual-read and cutover phases. Canary helps deploy the code that does the dual-write. But the safety comes from the migration pattern itself, not from the exposure mechanism. If your migration plan fits on a slide, the exposure mechanism will not save you.

How do we choose between LaunchDarkly, Statsig, and Unleash?

Cost, cohort semantics, and integration surface. LaunchDarkly is the most mature and the most expensive. Statsig has strong experimentation primitives baked in. Unleash is open source and self-hostable, which matters for regulated industries. All three integrate with cohort-aware guardrail systems. Pick on cost and org fit; the differences on the release side are small once you have a decision layer above them.

Halt bad releases before users notice

Lumanan watches every rollout cohort against error, latency, and business guardrails, then auto-rolls back and posts the receipt to Slack.

Request early access