Azure Deployment Stacks and Template Specs: Lifecycle for ARM Deployments

Yesterday ended on Bicep’s honest gap: incremental deployments never delete, and nothing stops a portal edit five minutes after your pipeline finishes. Deployment stacks are the platform’s answer to both, and template specs round out the distribution story. Together they give ARM native IaC the lifecycle semantics Terraform users take for granted, plus one thing Terraform cannot do at all.

Stacks: Managed Resources With Real Delete

A deployment stack is a resource that owns the resources its template deploys. Deploy the stack, and its managed resource list is the membership record; remove a resource from the template and redeploy, and actionOnUnmanage decides its fate: detach (leave it, classic ARM behavior) or delete (remove it, including optionally emptied resource groups). That single setting closes the orphan gap, the storage account that left the template in March but billed until someone noticed in November. Stacks deploy at resource group, subscription, or management group scope, and updating the stack with a changed template is the whole workflow, same idempotent redeploy as before, now with subtraction working.

az stack sub create \
  --name platform-connectivity \
  --location westeurope \
  --template-file connectivity.bicep \
  --parameters environment=prod \
  --action-on-unmanage deleteResources \
  --deny-settings-mode denyWriteAndDelete \
  --deny-settings-excluded-principals $PIPELINE_SP_OBJECT_ID

Deny Settings: The Feature Terraform Does Not Have

The second parameter above is the differentiator. Deny settings attach platform level deny assignments to the stack’s managed resources: denyDelete blocks deletion, denyWriteAndDelete blocks modification too, for everyone except the excluded principals, your deployment pipeline. This is drift prevention rather than drift detection: the portal edit that Terraform discovers in tomorrow’s plan simply fails today with a deny error. It outranks RBAC, an Owner on the subscription still cannot modify stack protected resources through the portal, which makes it the strongest “the pipeline is the only writer” enforcement in the platform. Use it deliberately: production landing zone and shared infrastructure stacks with denyWriteAndDelete and a tight exclusion list; application stacks perhaps denyDelete only, leaving room for the operational knobs teams legitimately turn; and remember excluded actions can whitelist specific operations (restarting an app, scaling) so day two operations survive inside the protection.

Template Specs: The Internal Catalog

Template specs store versioned templates as ARM resources: publish the compiled Bicep as spec version 2.1.0, grant read via RBAC, and consumers deploy it by resource ID from the portal, CLI, pipelines, or as the payload of a stack, no repo access required. That RBAC gated, portal deployable property is what makes specs the right distribution channel for the self service catalog: the golden dev environment, the compliant sandbox, the approved VM build, published by the platform team, deployed by anyone entitled, always from a pinned version. Specs and the ACR hosted Bicep module registry overlap less than they appear to: registry modules serve authors composing templates, specs serve consumers deploying finished products, and a mature setup uses both, modules inside, specs at the edge. Wire the publication into the release pipeline like any artifact, and the stack plus spec combination completes the picture this IaC week has drawn twice now, once per toolchain: versioned artifacts, gated deployment, enforced ownership, and subtraction that works.

Cheers
Osama

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.