Bicep Deployment Scopes

A scope is the Azure level where a deployment runs. Most Bicep files deploy into a resource group, which is the default. Some tasks, such as creating a resource group or assigning a policy, need a higher level. The targetScope line selects the level.

Azure organizes everything like nested boxes. A company holds departments, each department holds projects, and each project holds tools. A deployment picks the box where it places its items.

The Scope Hierarchy

 ┌─ Tenant ──────────────────────────────────────────────┐
 │  ┌─ Management Group ──────────────────────────────┐  │
 │  │  ┌─ Subscription ────────────────────────────┐  │  │
 │  │  │  ┌─ Resource Group ────────────────────┐  │  │  │
 │  │  │  │   Storage   Web App   Database      │  │  │  │
 │  │  │  └─────────────────────────────────────┘  │  │  │
 │  │  └───────────────────────────────────────────┘  │  │
 │  └─────────────────────────────────────────────────┘  │
 └───────────────────────────────────────────────────────┘

The Four Scope Values

targetScope ValueTypical UseCLI Command
resourceGroupStorage, web apps, databasesaz deployment group create
subscriptionResource groups, policies, budgetsaz deployment sub create
managementGroupPolicies across many subscriptionsaz deployment mg create
tenantManagement groups, organization-wide settingsaz deployment tenant create

Resource Group Scope

No targetScope line is needed. The deployment command names the resource group.

az deployment group create \
  --resource-group rg-shop \
  --template-file main.bicep

Subscription Scope

A subscription-level file creates resource groups. Set the scope at the top and name a location for the deployment record.

targetScope = 'subscription'

param location string = 'eastus'

resource rg 'Microsoft.Resources/resourceGroups@2024-03-01' = {
  name: 'rg-shop-dev'
  location: location
}
az deployment sub create \
  --location eastus \
  --template-file main.bicep

Mixing Scopes with Modules

A single file can create a resource group and deploy resources inside it. The module's scope property points at the new group.

targetScope = 'subscription'

resource rg 'Microsoft.Resources/resourceGroups@2024-03-01' = {
  name: 'rg-shop-dev'
  location: 'eastus'
}

module storage 'storage.bicep' = {
  name: 'storageDeploy'
  scope: rg
  params: {
    storageName: 'stshopdev001'
  }
}
  main.bicep (subscription scope)
        │
        ├── creates ──► rg-shop-dev
        │
        └── module ───► storage.bicep runs inside rg-shop-dev

One command builds the whole environment, from the empty subscription to the finished storage account.

Management Group and Tenant Scope

These levels suit governance teams. A management group file applies a policy to every subscription underneath it.

targetScope = 'managementGroup'
az deployment mg create \
  --management-group-id contoso-prod \
  --location eastus \
  --template-file policy.bicep

Tenant deployments need elevated permissions. Most learners work at the resource group and subscription levels.

Permissions by Scope

The account that deploys needs rights at the chosen level. Creating a resource group requires permission on the subscription. A deployer limited to one resource group cannot run a subscription-scope file.

Choosing the Right Scope

Start with the question "what am I creating?" Application resources such as storage, web apps, and databases belong to a resource group. Resource groups themselves, budgets, and subscription-wide policies belong to a subscription. Rules that must cover many subscriptions belong to a management group. Picking the lowest level that does the job limits the permissions a deployment needs and reduces the damage from a mistake.

A common layout uses two files. One subscription-scope file creates the resource group, and one resource-group-scope file holds the application. A pipeline runs the first file once and the second file on every release.

Summary

Scopes decide where a deployment runs. Resource group scope is the default, and targetScope selects subscription, management group, or tenant. A module's scope property deploys resources into a different group from the parent file, which allows one command to build an entire environment.