ARM Deployment Stacks now Public Preview!
Published Jul 20 2023 02:00 PM 13K Views

TL; DR – Deployment Stacks is a new resource type for managing a collection of Azure resources as a single unit for faster update and delete (cleanup), as well as more granular capabilities for preventing unwanted changes to resources. 

The Problem: managing the lifecycle (creates, updates, deletes) of resources across multiple Azure scopes (RG, MG, Sub) is both complex and time consuming. Ensuring critical resources have the proper guard rails in place also adds to the complexity of resource management.

  • Cleanup: resources with the same lifecycle are often created across multiple scopes, adding the complexity of many 1-to-1 operations for updating/deleting (e.g. deleting test Storage accounts or VMs across many RGs). 
  • Unwanted changes: many developers get contributor rights to certain scopes to work on their projects. Sometimes accidental changes can be done to resources (e.g. deleting a resources). 

Why Deployment Stacks?

As a native solution, Deployment Stacks will enable users to manage a collection of resources across scopes as a single atomic unit.

The Solution: 1st Party resource enabling 1-to-many CRUD operations and resource change prevention. 

  • Cleanup: easily delete or update resources across scopes with a single call to the deployment stack resource as a 1-to-many operation.
  • Unwanted changes: block changes to managed resources with deny settings capability of a deployment stack.

Deployment Stacks Docs Reference:

Before getting started, please install the prerequisites listed in our docs:

The Deployment Stack Resource

 A deployment stack is a resource that deploys a template file (ARM or Bicep) as a deployment object. Beyond the familiar capabilities of the deployments object, the resources a deployment stack creates are known as "managedResources" and can be easily updated/deleted with a single operation on the deployment stack. "managedResources" can be deleted directly via delete of a deployment stack or indirectly via updates to the template and "actionOnUnmanage" behavior of the deployment stack, specified via delete flags. Depending on the combination, a managed resource can become detached or deleted on the subsequent update to the deployment stack resource. To detach a resource is to disassociate it from a deployment stack and not delete it.   Unwanted changes to "managedResources" can be prevented with the deny settings mode capability, blocking writes and deletes with ability to exclude specific principals or actions.

Create and Update Deployment Stack Resource

A deployment stack can be created at different scopes, such as, Resource Group, Subscription, and Management Group scope. To create a deployment stack, we need the following:

  1. Create a main template (e.g. azuredeploy.json or main.bicep) that defines the "managedResources" to be created by the deployment stack.
  2. Decide on what Deny Setting (e.g. DenyDelete or DenyWriteAndDelete) to specify on creation of a deployment stack
  3. Decide on "actionOnUnmanage" behavior of "Detach" or "Delete". If no delete flag is specified, the default behavior is always "Detach". 

For example, here is a CLI command for creating a deployment stack at the subscription scope:








az stack sub create --name "storageStack-DevEnv" --template-file "testStorageAccounts.bicep" --location "westus" --deny-settings-mode "DenyDelete"









Note: Use 'az account set' to specify the subscription scope for this deployment stack. 


Required properties:

  • --name: name for the deployment stack resource - storageStack-DevEnv"
  • --template-file: main template to be deployed by the stack - "testStorageAccounts.bicep"
  • --location: region of deployment for the subscription scope stack - "westus"
  • --deny-settings-mode: setting for the deny assignment created by the stack - "DenyDelete"

In this example, the deployment stack created named "vmStack-DevEnv" is created at the subscription scope with deny setting of "DenyDelete" and actionOnUnmanage of "Detach". We can verify this by viewing the deployment stack resource with the following command:








az stack sub show --name "storageStack-DevEnv"








The result will contain all information on the specified deployment stacks object, such as, resource ID of the deployment stack, array of managed resources, deny setting configurations, and more, including the "actionOnUnmanage" behavior:








"actionOnUnmanage": {
    "managementGroups": "detach",
    "resourceGroups": "detach",
    "resources": "detach"









For this example, resources removed from the "testStorageAccounts.bicep" file will be removed from "managedResources" and continue to exist in Azure, on the next update to the deployment stack. If you decide that instead you want the resources removed from the template to be deleted from Azure, you can change the "actionOnUnmanage" behavior by sepcifying the proper delete flag:

  • --delete-resources: will delete resources and detach resource groups
  • --delete-all: will delete both resources and resource groups







az stack sub create --name "storageStack-DevEnv" --template-file "testStorageAccounts.bicep" --location "westus" --deny-settings-mode "DenyDelete" --delete-resources








Given the stack was updated with the flag "--delete-resources", the resulting state of "actionOnUnmanage" will be the following:








"actionOnUnmanage": {
    "managementGroups": "detach",
    "resourceGroups": "detach",
    "resources": "delete"








You can also view the deployment stack resource in the Azure portal by navigating to the scope at which it was created, and finding the Stacks options within Settings:




Beyond deciding on the behavior for "actionOnUnmanage" it is also important to define what deny setting mode should the deployment stack use. Today a deployment stack resource can have "--deny-settings-mode": 

  • None
  • DenyDelete: blocks managedResources from being deleted
  • DenyWriteAndDelete: blocks write and delete attempts to managedResources

In our initial example, we specified DenyDelete for our deny setting. Behind the scenes, a deployment stack resources creates a deny assignment for the managedResources. Meaning that users that got the test storage accounts provisioned can make updates/writes to those accounts but not delete them. In some cases, you might need some flexibility or stop gap measure for the deny assignment. For example, you may want to exclude a particular user from the deny assignment, such that they can go and delete the resource manually (outside of the context of a deployment stack), or maybe you want to exclude a particular action for all users. These options are available in the form of:

  • "--deny-settings-excluded-principals": excludes listed AAD principal IDs from the deny assignment 
  • "--deny-settings-excluded-actions": excludes listed RBAC actions from the deny assignment

Here is an example of what a command to create a deployment stack would look like with these flags set:





az stack sub create --name "storageStack-DevEnv" --template-file "testStorageAccounts.bicep" --deny-settings-mode "DenyDelete" --deny-settings-excluded-principals "12304812408-2148124081" --deny-settings-excluded-actions "Microsoft.Storage/storageAccounts/delete" --delete-resources --location "westus"



For more information on deployment stacks, please visit our docs and our GitHub. 



Version history
Last update:
‎Jul 20 2023 07:03 AM
Updated by: