Skip to main content

Resource groups and locks

A resource group is the container every Azure resource lives in, and a management lock stops a resource or group from being deleted until someone removes the lock. On the Azure platform each unit owns its own resource group, and the resources that would be expensive or impossible to rebuild carry a CanNotDelete lock.

What it does​

A resource group collects resources that share a lifecycle. Deleting the group deletes everything in it, role assignments can be made at the group, and cost views can be filtered by it. A management lock is set on a subscription, group or resource. CanNotDelete allows reads and changes but refuses every delete, for every principal including Owners, and a lock on a group protects everything inside it. Removing a lock needs Microsoft.Authorization/locks/delete, which Owner and User Access Administrator carry and Contributor does not.

How BuiltForProd uses it​

One group per unit. Every module that creates resources creates its own resource group: 26 in the Baseline modules, 10 in the Web App Blueprint and 3 in the Data and ETL Blueprint. Names follow root.hcl's name_prefix ({namespace}-{environment}-{stage}) plus the unit's purpose, such as acme-eus2-prd-kv-publish-rg, acme-eus2-security-observability-rg or acme-eus2-prd-aks-rg. The group is therefore the unit's scope for a lock, a role assignment or a cost filter, and a unit's resources never mix with another's. The one exception to the pattern is NetworkWatcherRG, which the subscription baseline creates under Azure's conventional name. Every repository generates its provider with prevent_deletion_if_contains_resources = true, so OpenTofu will not delete a group that still holds a resource it does not manage.

Locks in the Baseline. The units that hold state, evidence or shared foundations put a CanNotDelete lock on their resource group (the contract vault on the vault itself):

LockedUnitSubscription
State backend groupstate-backendacme-core-root
Baseline group of every subscriptionsubscription-baselineall 14
Audit workspace, audit storage, audit keyaudit-workspace, audit-storage, audit-cmkacme-core-audit
Security workspace and action groupobservability-sinkacme-core-security
SOPS key vaultsops-keysacme-core-security
Hub, spoke and runner virtual networksvnet-hub, vnet-spoke, vnet-runneracme-core-network, plat, acme-core-auto
Private DNS zones; public DNS zonesprivate-dns; dns-zonesacme-core-network; acme-core-dns
Container registry; metastore storageacr; uc-metastoreacme-core-artifacts
CI platform vaultplatform-kvacme-core-auto
Contract vaultkv-publisheach plat subscription

Most lock notes say the same thing: removal needs an activated Privileged Identity Management role, because of the groups in the access matrix only Owner can lift it (standing Owner while PIM is off). The audit trail has a second layer: the audit-protection initiative of Azure Policy denies deleting the audit workspace, the audit storage and any diagnostic setting, whatever the locks say.

Locks in the blueprints. The blueprints switch their locks per stage with delete_locks. In the Web App Blueprint it locks the application vault, the Cosmos DB for MongoDB vCore cluster and the Managed Redis cache; in the Data and ETL Blueprint the lake and Databricks workspace groups. Both stack files set it to true in prod and false in dev and staging, so lower stages can be torn down and rebuilt freely.

Terms you will see​

TermMeaning
Resource groupThe lifecycle and access container of a unit's resources.
name_prefix{namespace}-{environment}-{stage}, such as acme-eus2-prd; starts every name.
CanNotDeleteThe lock level that refuses deletes and allows every other operation.
delete_locksThe blueprints' per-stage switch for locks on their data and secrets.
NetworkWatcherRGThe one group named by Azure's convention instead of the prefix.

Where to read more​