Skip to content

Research: Azure Container Apps Deployment Labels vs Multiple Revisions

Reference: https://learn.microsoft.com/en-us/azure/container-apps/deployment-labels

Context

We currently implement blue/green deployments using activeRevisionsMode: Multiple — the workflow manually labels revisions, shifts traffic via az containerapp ingress traffic set, smoke-tests, and deactivates the old revision. Azure has since introduced a third revisions mode: Deployment Labels (revisions-mode: labels), which is purpose-built for this pattern.

This document compares the two approaches and outlines a migration plan if we decide to switch.


Current approach — Multiple revisions mode

How it works:

  1. Bicep deploys a new revision with revisionSuffix: green-<sha>-{be|fe|ui}
  2. Workflow locates the green revision by suffix
  3. Bootstraps blue label on first deploy (no existing label)
  4. Labels green revision, smoke-tests via direct FQDN
  5. Shifts traffic: green=100 blue=0
  6. Promotes green → blue label
  7. Deactivates old revision explicitly

Benefits:

  • Already implemented and merged
  • Smoke-test before cutover is explicit and controllable
  • Full control over traffic percentages at every step
  • No dependency on a newer Azure API feature (better availability across regions/preview status)

Drawbacks:

  • Bootstrap problem: first deploy requires special-casing when no blue label exists yet
  • Old revision cleanup is manual — a workflow bug could leave stale revisions running and incurring cost
  • Traffic shift logic is ~60 lines of bash across three apps — complex and fragile
  • Rollback is a separate workflow job that must locate the blue-labelled revision and shift traffic back manually
  • az containerapp ingress traffic set is a full replacement call — easy to misconfigure weights

Alternative — Deployment Labels mode

How it works:

  1. Bicep sets activeRevisionsMode: Labels
  2. Each deploy calls az containerapp update --target-label production (or stage)
  3. Azure automatically creates a new revision, assigns it the label, and shuts down the previous revision that was on that label
  4. Rollback: az containerapp label-history show + reassign label to any prior revision

Benefits:

  • Automatic revision lifecycle: Azure deactivates revisions no longer referenced by any label — no manual cleanup, no cost leakage from stale revisions
  • Rollback is native: label history is built in, no custom workflow job needed
  • Simpler workflow: az containerapp update --target-label <label> replaces ~60 lines of bash
  • No bootstrap problem: Azure manages label creation and promotion
  • Audit trail: full label history queryable via CLI

Drawbacks:

  • Smoke-test before cutover is not built in — traffic shifts immediately when the label is reassigned; we would need to deploy to a stage label first, smoke-test, then reassign production to that revision (two-step, still manageable)
  • Newer feature — may have regional availability or API maturity constraints worth validating
  • Requires changing activeRevisionsMode in Bicep from Multiple to Labels — ARM will reject a direct in-place change; needs a careful migration (deactivate old revisions first)
  • --target-label is not yet supported in all Bicep resource API versions — would need to verify the current Microsoft.App/containerApps API version supports it, or manage via CLI post-deploy

Side-by-side comparison

Dimension Multiple revisions (current) Deployment Labels
Revision cleanup Manual (az containerapp revision deactivate) Automatic
Rollback Custom workflow job, label reassignment via bash Built-in label history + az containerapp revision label add
Traffic shift Manual ingress traffic set with weight arithmetic Implicit on label reassignment
Smoke test before cutover Yes — built into workflow Requires two-label strategy (stage → production)
Bootstrap complexity First-deploy special-case required None
Workflow complexity ~60 lines bash per app ~5 lines per app
Bicep change required None (already deployed) activeRevisionsMode: 'Labels' — breaking change, needs migration
Feature maturity GA GA as of 2025 — verify northeurope/westeurope availability

Migration plan (if approved)

Phase 1 — Validate (no code changes)

  • [ ] Confirm revisions-mode: labels is available in westeurope and northeurope via az provider show
  • [ ] Confirm current Bicep API version (2024-03-01 or later) supports activeRevisionsMode: 'Labels'
  • [ ] Review whether --target-label is expressible in Bicep or CLI-only

Phase 2 — Bicep changes

  • [ ] Change activeRevisionsMode: 'Multiple''Labels' in infra/modules/container_apps.bicep for all three apps
  • [ ] Remove revisionSuffix parameter from all three app templates (Azure generates revision names)
  • [ ] Remove revision_suffix param from container_apps.bicep and main.bicep
  • [ ] Remove revision_suffix from both bicepparam files

Phase 3 — Workflow changes (deploy-application.yml)

  • [ ] Replace blue/green traffic shift bash function with az containerapp update --target-label production
  • [ ] Add a stage label step before cutover: deploy to stage, smoke-test, then reassign production
  • [ ] Remove rollback job (replace with az containerapp revision label add --label production --revision <sha> one-liner)
  • [ ] Remove revision_suffix input and all references

Phase 4 — Migration execution (prod)

  • [ ] Deploy dev first; verify label history appears, old revisions auto-deactivate
  • [ ] Confirm rollback works: az containerapp label-history show + label reassignment
  • [ ] Deploy prod

Phase 5 — Cleanup

  • [ ] Remove handoff-blue-green.md and plan-blue-green.md stale sections
  • [ ] Update MEMORY.md deployment flow notes

Recommendation

Do not migrate now. The current implementation works and is newly merged. The primary gains from labels mode are automatic cleanup and simpler rollback — real quality-of-life improvements but not blockers. Revisit after the v0.17.0-alpha release is stable in prod. At that point Phase 1 validation takes ~30 minutes and will confirm whether the migration is straightforward.