Azure Governance

Management Groups 101: Designing a Hierarchy That Scopes Policy and RBAC

You have eight subscriptions. Production, staging and dev for two product teams, a shared-services subscription for networking, and a sandbox where people try things. Security asks a simple question: “Can you guarantee that no one, anywhere, can spin up a resource in a banned region, and that the platform team has read access to everything for cost reporting?” If your answer is “I’ll apply the policy to each subscription, and add the RBAC assignment eight times,” you have just signed up to do that again every time someone creates a ninth subscription — and to remember. That is the gap management groups close.

A management group is a container that sits above subscriptions. It is a node in a tree whose leaves are subscriptions, and the entire point of the tree is inheritance: a policy or a role assignment placed on a management group flows down to every subscription beneath it, and to every resource group and resource inside those subscriptions, automatically and forever — including subscriptions that do not exist yet. You assign once, at the right altitude, and Azure enforces it everywhere below. This article is about that altitude: what management groups are, how the four levels of the scope hierarchy inherit governance, and — the part that actually matters — how to shape the tree so it scopes policy and access cleanly instead of becoming a tangle you are afraid to touch.

By the end you will be able to read any management-group hierarchy and predict what a given subscription inherits, design a tree that mirrors how your organization actually governs (not how its org chart happens to look this quarter), and avoid the handful of structural mistakes — flat trees, environment-vs-team confusion, deny-at-the-wrong-level — that force expensive re-parenting later. This is a Basic, concept-first article: we lead with mental models and decision tables, walk one reference architecture, and keep the CLI and Bicep close so you can build it the same afternoon.

What problem this solves

Without management groups, a subscription is your highest unit of governance, and that creates two specific pains. The first is repetition: every guardrail — allowed regions, required tags, denied SKUs, a “platform reads everything” role — has to be stamped onto each subscription individually. With three subscriptions that is tedious; with thirty it is unmanageable, and the real failure mode is drift. Someone creates a new subscription, forgets two of the eleven standard policies, and now you have a compliance hole that no one notices until an audit or an incident. Governance that depends on humans remembering to repeat themselves is governance that is already broken.

The second pain is the absence of a place to express organization-wide intent. “Everything in this company must deny public blob access” is a sentence about the whole tenant, but without management groups there is no object that means “the whole tenant” — only a pile of subscriptions you have to enumerate. You cannot assign a policy to “all of it” because “all of it” is not a thing Azure can point at. Management groups give you that thing: the tenant root group at the very top means everything, and every management group below it means some coherent slice of everything.

Who hits this: any organization past its second or third subscription, and especially anyone adopting an enterprise-scale landing zone, where the management-group tree is the literal foundation everything else is poured onto. It bites hardest when a tenant grows organically — subscriptions created ad hoc, governance bolted on per-subscription — and then someone tries to impose consistent policy and discovers there is no lever that reaches all of it at once. Management groups are the lever. The cost of not using them is paid later, in a migration where you re-parent live subscriptions and pray the inherited policy doesn’t break a running workload.

Pain without management groups What it looks like in production What management groups give you
Policy repeated per subscription 30 subscriptions, each configured by hand; new ones drift Assign once at a group; all subs below inherit
No “whole tenant” object “Deny public IPs everywhere” has nowhere to live Tenant root group = everything; assign there
RBAC re-granted per subscription Platform team added to each sub manually One assignment at root; reads everything below
New subscriptions start ungoverned Day-one gap until someone configures them New sub placed in a group inherits instantly
No blast-radius boundary for guardrails A bad deny hits all subs at once or none Scope the deny to one branch of the tree

Learning objectives

By the end of this article you can:

Prerequisites & where this fits

You should already understand that Azure has a resource hierarchy: resources (a VM, a storage account) live in resource groups, resource groups live in subscriptions, and a subscription is a billing-and-isolation boundary. If those three levels are fuzzy, read Azure Resource Hierarchy Explained: Subscriptions, Resource Groups and Resources first — management groups add a fourth level above all of it, and the inheritance story only makes sense once the bottom three are clear. It also helps to know what a subscription actually is and when you create a new one, covered in Azure Subscriptions Explained: Types, Billing Boundaries and When to Create a New One.

Two adjacent topics are the reason management groups exist, and we lean on both: Azure Policy (the rules that get inherited) and Azure RBAC (the access that gets inherited). You do not need to be expert in either, but a working idea of “a policy denies or audits something” and “a role assignment grants someone permissions at a scope” will make every inheritance example land. The deep treatment of the rules themselves lives in Azure Policy and Governance at Scale: Enforce the Rules Automatically.

Where this fits in the bigger picture: management groups are the top of the governance stack and the foundation of a landing zone. In an Azure Enterprise-Scale Landing Zone: Foundation for Large Organizations, the management-group hierarchy is laid down first, before any workload subscription exists, because everything else — policy, RBAC, networking topology — is scoped onto it. Get the tree right and the rest has somewhere solid to attach. Get it wrong and you re-pour the foundation with the house already standing on it.

You should know Why it matters here Where to learn it
Resource group → subscription nesting MGs add the level above; inheritance is the whole point Azure Resource Hierarchy Explained
What a subscription is / when to make one Subscriptions are the leaves your tree organizes Azure Subscriptions Explained
Azure Policy basics (deny / audit) Policy is the thing that inherits down the tree Azure Policy and Governance at Scale
RBAC role assignment at a scope Role assignments inherit down too Azure Policy and Governance at Scale
Landing-zone concept (optional) The MG tree is its literal foundation Azure Enterprise-Scale Landing Zone

Core concepts

Four mental models make every later decision obvious. Read these slowly; the rest of the article is just consequences of them.

A management group is a node in a tree, and the tree has exactly one root. Every Azure tenant has a single, immovable tenant root group (its ID is the tenant/directory ID itself). It is created automatically, you cannot delete or move it, and it is the ancestor of everything. Under it you build a tree of management groups — groups inside groups — and at the bottom, as leaves, sit your subscriptions. A subscription has exactly one parent management group at any time (it cannot belong to two), and a management group can hold both child management groups and subscriptions. The shape of this tree is the only thing you design; the inheritance comes for free.

Inheritance flows strictly downward, and it is cumulative. This is the engine. A policy assignment or a role assignment placed at any node applies to that node and everything beneath it — all descendant management groups, all subscriptions in that branch, all their resource groups, all their resources. It is cumulative, not override-by-proximity: if the root says “deny resources outside India regions” and a child group says “require a costCenter tag,” a subscription two levels down gets both. Crucially for security, RBAC and policy cannot be revoked lower down — a child cannot “turn off” a deny inherited from a parent. The higher you place an assignment, the broader and more unstoppable its reach. That is the lever, and also the footgun.

The four scope levels are one continuous ladder. Azure assigns policy and RBAC at exactly four levels, broadest to narrowest: management group → subscription → resource group → resource, forming a single inheritance chain. Management groups simply extend the ladder you already use upward past the subscription — so a guardrail can now reach across many subscriptions at once. Nothing about how inheritance works is new; there is just a new, higher place to stand.

Effective governance is the union of every level above you. “What does subscription X enforce?” is answered by summing every policy and role assignment from the tenant root down through each ancestor, plus anything on the subscription and its contents. A resource is governed by all its ancestors at once — which is why placement is a design decision: the rung you choose decides the blast radius.

The four scope levels, side by side

Scope level What it contains Assign policy here to govern… Assign RBAC here to grant access to… Can you nest it?
Tenant root group All management groups + all subscriptions The entire tenant — every subscription, forever Everything in the tenant (use sparingly) It is the single root; nothing above
Management group Child MGs and/or subscriptions That whole branch of the tree All subscriptions in that branch Yes — up to 6 levels below root
Subscription Resource groups One subscription and all its resources One subscription’s resources No (leaf of the MG tree)
Resource group Resources All resources in the group Resources in that group No
Resource (the thing itself) Just that resource Just that resource No

Inheritance in one table

The single most important behaviour, made concrete. Read each row as “an assignment placed here is in effect there”:

Assigned at… In effect at the subscription? At its resource groups? At individual resources? Can a lower scope cancel it?
Tenant root group Yes (every subscription) Yes Yes No
A parent management group Yes (subs in that branch) Yes Yes No
The subscription itself Yes Yes Yes No
A resource group n/a Yes (that RG only) Yes (in that RG) No
A resource n/a n/a Yes (that one) n/a

The “cannot cancel it lower down” column is the rule people forget. There is no allow that beats an inherited deny; you cannot un-assign a parent’s role from a child. If a guardrail is in the wrong place, you fix it at the level where it was assigned, not below.

How management groups inherit policy

Azure Policy is the primary reason management groups exist. A policy definition describes a rule (“resources must be in centralindia or southindia”); an assignment binds that definition to a scope and turns it on. Place the assignment on a management group and it evaluates against every resource in every subscription beneath it. The effect — Deny, Audit, Modify, DeployIfNotExists and others — is what happens when a resource matches; for the full effect catalogue see Azure Policy Effects Decoded: Deny vs Audit vs Modify vs DeployIfNotExists.

The design value is that you assign organization-wide guardrails once, at the right node. A Deny on “public network access for storage” at a management group means no team in that branch can ever expose a storage account publicly — not today, not in a subscription created next year. Compare that to per-subscription assignment, where the next subscription is a gap until someone remembers. Inheritance turns “remember to apply the rule” into “the rule is structurally unavoidable below this node.”

Three placement patterns cover almost everything, and choosing among them is the whole skill:

Policy intent Assign it at… Why there What it would cost you elsewhere
Non-negotiable tenant rule (e.g. allowed regions, no public IPs) Tenant root or a top-level MG Reaches everything; impossible to miss a sub Per-sub assignment drifts as subs grow
Environment-specific (e.g. stricter SKUs in prod) The prod management group Hits all prod subs, leaves dev free Stamping prod subs one by one
Team-specific exception or standard That team’s management group Scoped to the branch that needs it Polluting other teams with a niche rule

Two behaviours to internalise. First, policy is cumulative down the tree — a subscription is evaluated against the union of every assignment on every ancestor, so a resource can be denied by a root policy and audited by a mid-tree policy at the same time. Second, exemptions are deliberate and scoped: when a legitimate workload must violate an inherited policy, you create a policy exemption at the specific subscription or resource group, which is an explicit, auditable carve-out — not a way for a child to silently override a parent. Grouping many related rules into one assignable bundle is the job of initiatives (policy sets); when to bundle versus assign individually is covered in Policy Definitions vs Initiatives: When to Bundle Controls into a Set.

# Assign a built-in "allowed locations" policy to a management group.
# Every subscription under mg-corp now inherits the region restriction.
MG_ID="/providers/Microsoft.Management/managementGroups/mg-corp"
az policy assignment create \
  --name "allowed-locations-corp" \
  --display-name "Allowed locations (Corp)" \
  --scope "$MG_ID" \
  --policy "e56962a6-4747-49cd-b67b-bf8b01975c4c" \
  --params '{ "listOfAllowedLocations": { "value": ["centralindia","southindia"] } }'
// The same assignment as Bicep, deployed at management-group scope.
targetScope = 'managementGroup'

resource allowedLocations 'Microsoft.Authorization/policyAssignments@2024-04-01' = {
  name: 'allowed-locations-corp'
  properties: {
    displayName: 'Allowed locations (Corp)'
    // Built-in "Allowed locations" definition ID:
    policyDefinitionId: '/providers/Microsoft.Authorization/policyDefinitions/e56962a6-4747-49cd-b67b-bf8b01975c4c'
    parameters: {
      listOfAllowedLocations: { value: [ 'centralindia', 'southindia' ] }
    }
  }
}

How management groups inherit RBAC

Azure role-based access control (RBAC) inherits down the exact same tree. A role assignment binds a principal (a user, group, or managed identity), a role definition (Owner, Contributor, Reader, or a custom role) and a scope. Assign it on a management group and the principal holds that role across every subscription, resource group and resource in the branch. This is how you give the platform team Reader over the whole estate with a single assignment, or how you grant a product team Contributor over only their environment by assigning at their management group rather than per-subscription.

The economics mirror policy: one assignment at the right altitude replaces N assignments that would otherwise drift. But RBAC carries a sharper warning, because access is more dangerous than a guardrail. An Owner or Contributor assignment at a management group is enormous — it grants that principal control over everything below, including subscriptions added later. The right instinct is least privilege by altitude: grant broad-but-read-only roles (like Reader for visibility, or Management Group Reader) high in the tree, and grant powerful roles (Owner, Contributor) as low as the job allows — ideally at the subscription or resource group, not the management group.

Role assigned at a management group What the principal can do in the branch When this is appropriate The risk if over-scoped
Reader View everything below; change nothing Platform/cost teams needing estate-wide visibility Low — read-only, but still sees all metadata
Contributor Create/modify resources, but not grant access Rare at MG level; maybe a whole-environment ops team High — can change every workload in the branch
Owner Full control including assigning roles Almost never at MG level Severe — can grant others access estate-wide
User Access Administrator Manage role assignments below Break-glass / dedicated identity admins only Severe — can self-escalate across the branch
Custom role (scoped actions) Exactly the actions you defined Tailored platform automation Depends on the actions granted

One operational subtlety worth knowing on day one: managing the management-group tree itself — creating, moving, or assigning at the root — requires elevated rights, and by default even a Global Administrator must first be granted access at the root group (Azure provides an “elevate access” path for this). This is a safety feature, not a bug: it stops anyone from quietly attaching policy or RBAC at the most powerful node in your tenant.

# Grant the platform team READ over the entire Corp branch with ONE assignment.
PLATFORM_GROUP_OBJECT_ID="<entra-group-object-id>"
az role assignment create \
  --assignee-object-id "$PLATFORM_GROUP_OBJECT_ID" \
  --assignee-principal-type Group \
  --role "Reader" \
  --scope "/providers/Microsoft.Management/managementGroups/mg-corp"
// Reader for the platform group, at management-group scope.
targetScope = 'managementGroup'

@description('Object ID of the platform-team Entra group')
param platformGroupObjectId string

var readerRoleId = 'acdd72a7-3385-48ef-bd42-f606fba81ae7' // built-in Reader

resource platformReader 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
  name: guid('mg-corp', platformGroupObjectId, readerRoleId)
  properties: {
    principalId: platformGroupObjectId
    principalType: 'Group'
    roleDefinitionId: tenantResourceId('Microsoft.Authorization/roleDefinitions', readerRoleId)
  }
}

Designing the hierarchy: the shapes that work

Now the actual design question: what shape should the tree be? There are three canonical patterns, and the right answer is almost always a small hybrid. The mistake is treating this as an org-chart exercise. You are not modelling who reports to whom; you are modelling how governance differs. Two subscriptions belong under different management groups when they need different policy or different access — not because they belong to different VPs.

By environment groups subscriptions as prod, non-prod (or dev/test), sandbox. The win: environment is usually where guardrails genuinely differ — prod denies risky SKUs and demands tags; dev is looser. The cost: a single team’s prod and dev subs live in different branches, so a team-wide role needs assigning in two places.

By business unit (or team) groups subscriptions as retail, payments, corp-it. The win: each unit’s access and chargeback map cleanly to one branch. The cost: enforcing “prod is strict everywhere” now means repeating the prod policy inside every unit’s branch — the very repetition you came here to avoid.

Hybrid (business unit, then environment) nests environment inside each unit, or environment at the top with units below. This is what most mature tenants and the official landing-zone guidance converge on: a top-level split that captures the platform vs workloads distinction, then environment, with team scoping handled by RBAC rather than extra tree depth.

Approach Group the tree by… Best when Weak when Typical depth
By environment prod / non-prod / sandbox Guardrails differ mostly by environment (common) Per-team access is the dominant need 1–2 levels
By business unit retail / payments / corp Chargeback and team autonomy dominate Environment guardrails must be uniform 1–2 levels
Hybrid platform vs workloads, then env Large org adopting a landing zone Tiny tenants (it’s overkill) 2–3 levels
Flat (single MG) one MG over all subs < ~5 subs, uniform governance Any divergence in policy/access appears 1 level

A reliable decision table for “do these two subscriptions belong in the same group?”:

If the two subscriptions… Then… Because
Need the same policies and the same access Put them in the same management group Inheritance gives both, with one assignment
Differ only in policy strictness (prod vs dev) Separate by environment Scope the strict policy to the prod branch only
Differ only in who has access (team A vs B) Keep one tree; separate via RBAC scope Don’t add tree depth just for access
Are experimental / throwaway Put them in a dedicated sandbox group Keep loose rules out of the strict branches
Are being retired Move to a decommissioned group Park them under quarantine policy, then delete

Three structural elements that the landing-zone pattern makes standard and that pay off even in a modest tenant: a dedicated platform branch (sometimes split into identity, management, connectivity) for the shared subscriptions that run the estate — hub network, central logging, identity — which have a different governance profile from workloads; a sandbox branch held outside the strict guardrails so engineers can experiment without breaking or being blocked by the rules; and a decommissioned quarantine node with deny-most policy where you park subscriptions on their way out.

What you can and can’t do: rules and limits

Management groups are simple objects, but a few hard rules and real limits shape every design. Knowing them up front prevents the “why won’t it let me” moments.

Property Rule / limit Design implication
Management groups per tenant Up to 10,000 Effectively unlimited for structure; you’ll never hit it
Hierarchy depth Up to 6 levels below the root group Stay shallow (2–3); depth is a smell, not a feature
Levels including root and subscription 6 MG levels + root + the subscription layer Don’t design for maximum depth
Children per management group Up to 10,000 direct children (MGs + subs) A wide group is fine; a deep tree is not
Parents per subscription Exactly one at any time A sub can’t be governed by two branches at once
Tenant root group Auto-created; cannot be moved or deleted Don’t put workload-specific policy on the root
Moving a subscription/MG Allowed, but inherited governance changes instantly Re-parenting can apply or remove deny rules live
Deleting a management group Must be empty (no child MGs or subs) first Drain a branch before deleting it
Region Management groups are global, not regional No region to choose; metadata replicates globally

The two rules that catch people are one parent per subscription and move re-applies inheritance instantly. Because a subscription has a single parent, you cannot have it inherit from both a payments branch and a prod branch simultaneously — you choose one axis as the tree and express the other through policy or RBAC scoping. And because moving a subscription changes its ancestors immediately, a re-parent is a governance change: drag a sub from sandbox into prod and it instantly inherits every prod deny — which may block a resource that was happily running a minute ago. Treat moves as deployments, not drag-and-drop.

Architecture at a glance

The diagram below is the canonical small-but-real hierarchy, read left to right as four governance zones. On the far left is the tenant root group — the single immovable node that means “everything.” This is where you place only the truly universal, non-negotiable assignments: a Reader role for the platform team so they can see the whole estate, and perhaps one or two Deny policies that must hold tenant-wide (allowed regions, no public blob). Nothing workload-specific lives here, because anything on the root reaches every subscription including ones not yet created.

From the root the tree branches into the second zone, the top-level split that every landing zone uses: a platform management group for the subscriptions that run the estate (hub networking, central logging, identity), and a workloads (often called landing-zones) management group for everything the product teams build. Under workloads sits the third zone, the environment tier — a prod group carrying the strict guardrails and a non-prod group that is deliberately looser — plus a sandbox group hung off the top level, outside the strict branch, so experimentation never collides with production policy. The fourth zone is the leaves: the actual subscriptions, each inheriting the cumulative union of every policy and role from the root down through its specific branch. Follow any left-to-right path and you can read exactly what that subscription enforces: root rules, plus its branch’s rules, plus its environment’s rules. The numbered badges mark the four places where placement decisions bite — and the legend turns each into a “what goes here, and what happens if you get it wrong.”

Azure management-group hierarchy showing the tenant root group on the left with tenant-wide Reader RBAC and allowed-regions deny policy, branching into a platform management group (hub network, central logging subscriptions) and a workloads management group, which splits into prod (strict deny policy) and non-prod environment groups holding their subscriptions, plus a sandbox group hung outside the strict branch; arrows show policy and RBAC inheritance flowing strictly downward from root to subscriptions, with numbered badges on the root, the prod policy node, the sandbox, and a subscription leaf

Real-world scenario

Northwind Retail runs two engineering groups — Storefront and Payments — across eight subscriptions: prod and non-prod for each team, a shared networking subscription, a central logging subscription, and a sandbox. For their first two years everything lived as eight independent subscriptions. Governance was a wiki page titled “things to set up when you make a subscription,” and it was followed about 70% of the time. The breaking point came during a security review: an auditor asked Northwind to prove that no subscription allowed storage accounts with public network access. The platform lead could not — three subscriptions had the policy, five did not, and nobody could say why. Worse, granting the new central FinOps analyst read access to “everything” meant eight separate role assignments, and she was missing two of them, so her cost reports silently excluded the networking and logging subs.

The fix was a management-group hierarchy, designed in an afternoon and rolled out over a week. They created a top-level split: an mg-platform group for the networking and logging subscriptions, and an mg-workloads group for the product subscriptions. Under workloads they added mg-prod and mg-nonprod, and they hung mg-sandbox directly off the root, deliberately outside the strict branch. They placed the “deny public storage” and “allowed regions (central/south India)” policies on the tenant root group so the rule was structurally impossible to miss — every current subscription and every future one inherits it. They assigned Reader to the FinOps Entra group at the root too: one assignment, total visibility, and it auto-covers any subscription added later.

The most instructive part was the migration. When they moved the two prod subscriptions under mg-prod, which carried a stricter Deny on a legacy VM SKU, one Payments prod subscription had three running VMs on exactly that denied SKU. The deny does not delete existing resources — but it blocked the team’s next scale-out deployment with a clear policy-violation error, which is precisely what surfaced the problem. Northwind created a time-boxed policy exemption scoped to that one subscription, opened a ticket to migrate the VMs to a supported SKU, and set the exemption to expire on the migration deadline. The lesson the platform lead wrote on the (now much shorter) wiki page: re-parenting a subscription is a governance change — diff the inherited policy before you move, not after. Six months on, new subscriptions are created empty and dropped into the right group; they inherit the full guardrail set on creation, and the “things to set up” checklist is two lines long.

Advantages and disadvantages

Advantages Disadvantages
Assign policy and RBAC once, inherited by all subs below — including future ones Inheritance is invisible at lower scopes; people forget why a deny exists
A single object that means “the whole tenant” for org-wide rules A misplaced deny/role at a high node has a huge blast radius
New subscriptions are governed from creation (no day-one gap) Only one parent per subscription — can’t model two axes in the tree
Free — no cost for the groups themselves Managing the tree needs elevated rights (root access elevation)
Mirrors and enables the enterprise-scale landing zone Over-deep trees become confusing and slow to reason about
Re-parenting instantly re-applies the right governance Re-parenting also instantly re-applies it — can break live workloads
Estate-wide reporting/visibility via one Reader grant Strict prod policy can block legitimate deploys without exemptions

The advantages dominate the moment you pass a handful of subscriptions; below that, a flat single-management-group structure (or even none) is genuinely fine and the tree is overhead. The disadvantages are almost all placement problems, not tool problems — they bite when an assignment sits at the wrong altitude. Two disciplines neutralise most of them: keep the tree shallow so the inheritance chain is short enough to hold in your head, and document at the assignment why each high-level policy or role exists, because the person debugging a mysterious deny six months from now is staring at a subscription with no local assignment and no clue it’s coming from three levels up.

Hands-on lab

This lab builds a minimal real hierarchy, assigns an inherited policy, proves the inheritance, then tears it down. It needs only an Azure account where you have rights to manage management groups (you may need to elevate access at the root once). Everything here is free.

1. Sign in and confirm you can see the root group.

az login
# List existing management groups (you'll at least see the tenant root group)
az account management-group list -o table

2. Create the top-level split. Create mg-corp under the root, then mg-workloads under it.

# Top-level group under the tenant root
az account management-group create --name "mg-corp" --display-name "Corp"

# Child group nested under mg-corp
az account management-group create --name "mg-workloads" \
  --display-name "Workloads" --parent "mg-corp"

3. Create the environment tier. Add mg-prod and mg-nonprod under workloads.

az account management-group create --name "mg-prod" \
  --display-name "Production" --parent "mg-workloads"
az account management-group create --name "mg-nonprod" \
  --display-name "Non-Production" --parent "mg-workloads"

4. Inspect the tree. Pull the hierarchy and confirm the nesting.

# Expand the tree from mg-corp downward
az account management-group show --name "mg-corp" --expand --recurse \
  --query "{name:displayName, children:children[].{name:displayName, type:type}}" -o json

Expected: mg-corp with a child Workloads, which itself has children Production and Non-Production.

5. Move a subscription into the tree. Use a non-production subscription you own (substitute its ID). This re-parents it under mg-nonprod.

SUB_ID="<your-nonprod-subscription-id>"
az account management-group subscription add \
  --name "mg-nonprod" --subscription "$SUB_ID"

6. Assign an inherited policy at mg-corp. This “allowed locations” assignment now covers every subscription in the branch — including the one you just moved.

az policy assignment create \
  --name "allowed-locations-lab" \
  --display-name "Allowed locations (lab)" \
  --scope "/providers/Microsoft.Management/managementGroups/mg-corp" \
  --policy "e56962a6-4747-49cd-b67b-bf8b01975c4c" \
  --params '{ "listOfAllowedLocations": { "value": ["centralindia","southindia"] } }'

7. Prove the inheritance from the subscription’s point of view. List policy assignments effective at the subscription — the lab assignment appears even though it was set three levels up.

az policy assignment list --scope "/subscriptions/$SUB_ID" \
  --query "[].{name:name, scope:scope}" -o table
# You should see 'allowed-locations-lab' with a management-group scope.

8. (Optional) Watch the guardrail bite. Try to create a resource group in a disallowed region; the inherited policy denies it.

az group create --name "rg-deny-test" --location "westeurope" --subscription "$SUB_ID"
# Expect: RequestDisallowedByPolicy — disallowed by the inherited 'allowed-locations-lab'.

9. Tear down — order matters. Remove the assignment, move the subscription back to the root, then delete the groups from the leaves up (a group must be empty to delete).

az policy assignment delete --name "allowed-locations-lab" \
  --scope "/providers/Microsoft.Management/managementGroups/mg-corp"

# Re-parent the subscription back under the tenant root before deleting groups
TENANT_ROOT=$(az account management-group list --query "[?contains(displayName,'Tenant Root')].name | [0]" -o tsv)
az account management-group subscription add --name "$TENANT_ROOT" --subscription "$SUB_ID"

# Delete leaf-first
az account management-group delete --name "mg-prod"
az account management-group delete --name "mg-nonprod"
az account management-group delete --name "mg-workloads"
az account management-group delete --name "mg-corp"

To define the same tree declaratively (the production approach — version-control your hierarchy), the management groups themselves are Bicep at tenant scope:

// hierarchy.bicep — deploy with: az deployment tenant create
targetScope = 'tenant'

resource corp 'Microsoft.Management/managementGroups@2023-04-01' = {
  name: 'mg-corp'
  properties: { displayName: 'Corp' }
}

resource workloads 'Microsoft.Management/managementGroups@2023-04-01' = {
  name: 'mg-workloads'
  properties: {
    displayName: 'Workloads'
    details: { parent: { id: corp.id } }
  }
}

resource prod 'Microsoft.Management/managementGroups@2023-04-01' = {
  name: 'mg-prod'
  properties: {
    displayName: 'Production'
    details: { parent: { id: workloads.id } }
  }
}

Common mistakes & troubleshooting

The failure modes here are rarely “the tool is broken” — they are placement and inheritance surprises. Each row: the symptom, the real cause, the exact way to confirm it, and the fix.

# Symptom Root cause Confirm with Fix
1 A deployment fails with RequestDisallowedByPolicy but the subscription has no such policy The deny is inherited from an ancestor management group az policy assignment list --scope /subscriptions/<id> (note the MG-scoped entry) Move the assignment, scope it tighter, or add a scoped exemption
2 Removing a role at the subscription doesn’t revoke a user’s access The role was assigned at a parent management group az role assignment list --scope /subscriptions/<id> --include-inherited Remove it at the MG where it was assigned, not the sub
3 “You don’t have permission to manage at this scope” on the root Root-group management needs elevated access first Check whether access was elevated for your account Elevate access at the tenant root (one-time, by an admin)
4 A subscription seems ungoverned despite policies on its team’s group The sub is parented under the wrong management group az account management-group show --name <mg> --recurse Re-parent the subscription into the correct branch
5 Can’t delete a management group The group still contains child groups or subscriptions az account management-group show --name <mg> --expand Move/drain all children, then delete (leaf-first)
6 Moving a sub into prod suddenly breaks running deploys Prod branch carries a deny the workload violates Diff inherited policy before moving; read the deny error Exemption (time-boxed) + remediate the workload
7 A guardrail you set “everywhere” misses one subscription That subscription sits outside the branch you assigned to Trace the sub’s parent chain to the root Re-parent it, or assign higher (e.g. tenant root)
8 Policy assignment at an MG isn’t evaluating new resources Evaluation is not instant; compliance scan lags Trigger an on-demand scan; check the assignment scope Wait for the scan or run az policy state trigger-scan
9 A DeployIfNotExists/Modify policy at an MG never remediates The policy’s managed identity lacks rights in the branch Check the assignment’s identity and its role Grant the assignment identity the required role at the MG
10 Two teams fight over one subscription’s policies Trying to model two axes (team and env) in one tree Look at the sub’s single parent chain Pick one axis for the tree; express the other via RBAC scope

The meta-lesson across all ten: when a subscription is governed (or not) and has no matching local assignment, walk up the tree — the answer is almost always at an ancestor. --include-inherited (roles) and the scope field on policy assignments (policy) find it fast.

Best practices

Security notes

Management groups are a security control, so the security discipline is mostly about not turning them into a liability. The dominant risk is over-scoped RBAC at a high node: an Owner or User Access Administrator assignment at the tenant root or a top-level group is one of the most powerful grants in the entire tenant, because it confers control over every subscription beneath it, present and future. Treat assignments at the root and top-level groups as privileged actions — restrict who can make them, and audit them. Microsoft deliberately requires elevating access to manage the root group precisely so this node cannot be quietly modified.

Use management groups offensively for security, too: a Deny policy at the tenant root is the strongest possible guardrail because nothing below can cancel it. Tenant-wide rules — deny public blob access, deny resources outside approved regions, require encryption, deny classic (non-ARM) resources — belong here, where they are structurally unavoidable. For the visibility side, a single Reader (or Security Reader) assignment for your security team at the root gives estate-wide read coverage that automatically extends to new subscriptions, closing the gap where a freshly created subscription would otherwise be invisible to monitoring.

Security concern At management-group level Practical rule
Least privilege Broad roles here have estate-wide reach Grant Owner/Contributor as low as possible
High-blast-radius assignments Root/top-level Owner controls everything Restrict and audit who can assign at the root
Universal guardrails Root Deny cannot be overridden below Put non-negotiable denies on the tenant root
Estate-wide visibility One Reader/Security Reader covers all subs Assign it high so new subs are covered automatically
Identity hygiene Group-based assignment, not per-user Assign to Entra groups; manage membership centrally
Break-glass control User Access Administrator can self-escalate Reserve for dedicated, monitored break-glass identities

Cost & sizing

The headline number is the easy part: management groups are free. There is no charge for the groups, the hierarchy, or the policy and RBAC inheritance they enable. You are not “sizing” a management group the way you size a VM — there is no SKU, no region, no capacity to provision. Their cost is entirely design effort and operational discipline, and the relevant “limits” are structural, not financial.

What management groups do for cost is indirect but significant. Because the tree mirrors how you want to report and govern spend, it is the natural place to attach FinOps practices: cost views, budgets, and tag-enforcement policies scoped to a branch. A Modify/Append policy at a management group that enforces a costCenter tag on every resource turns chaotic billing into clean, allocatable spend across the whole branch — which is exactly the foundation Azure FinOps and Cost Management: Controlling Cloud Spend at Scale builds on. For first-30-days budget and alert basics that you then scope to your tree, see Azure Cost Management for Beginners: Budgets, Alerts and Cost Analysis in Your First 30 Days.

“Sizing” question The real answer Guidance
What does a management group cost? Nothing — they are free Cost is design + discipline, not money
How deep should the tree be? 2–3 levels below root Limit is 6; depth is a smell, not a goal
How many groups should I create? As many as governance differs Don’t create a group without a distinct policy/access reason
When is a flat structure fine? Roughly under ~5 subs, uniform rules A single MG (or none) is genuinely OK then
Where does cost governance attach? Tag-enforcement policy at the branch Scope Modify/budgets to the MG that owns the spend

Interview & exam questions

These map to AZ-104 (Azure Administrator) and AZ-305 (Solutions Architect), where management-group design and governance inheritance are recurring themes.

1. What is a management group and why would you use one? A management group is a container above subscriptions in the Azure scope hierarchy. You use it to apply policy and RBAC once, at a node, and have it inherited by every subscription, resource group and resource beneath — eliminating per-subscription repetition and governing new subscriptions automatically.

2. Name the four scope levels Azure assigns policy and RBAC at, broadest to narrowest. Management group → subscription → resource group → resource. Assignments at a higher level are in effect at every lower level via inheritance.

3. How does inheritance behave when a parent and child both have policy? It is cumulative, not override-by-proximity. A subscription gets the union of all ancestor assignments; a child cannot cancel a parent’s deny. Effective governance is the sum of everything from the tenant root down.

4. A subscription can have how many parent management groups? Exactly one at any time. This is why you choose a single axis (e.g. environment) for the tree and express other axes (e.g. team) through RBAC scoping rather than a second parent.

5. What is the tenant root group, and what should you put on it? The single, auto-created, immovable group at the top, whose ID is the tenant ID. Put only truly universal assignments there — allowed regions, deny public access, a platform-team Reader role — because anything on it reaches every subscription, including future ones.

6. Why is an Owner assignment at a management group risky? It grants full control, including the ability to assign roles, over every subscription in the branch — present and future. The blast radius is enormous, so powerful roles should be assigned as low as the job allows, and broad/read-only roles kept high.

7. You moved a subscription under the prod management group and a deployment started failing. Why? Re-parenting applies the new ancestors’ governance instantly. The prod branch likely carries a Deny the workload violates. Confirm by listing the subscription’s effective policy assignments; fix with a scoped, time-boxed exemption plus remediation.

8. How do you let one workload legitimately violate an inherited policy? Create a policy exemption scoped to that subscription or resource group — an explicit, auditable carve-out — rather than weakening the parent policy for everyone in the branch.

9. What’s the difference between organizing the tree by environment versus by business unit? By environment (prod/non-prod) aligns the tree with where guardrails differ, which is usually environment. By business unit aligns with chargeback and team autonomy but forces repeating environment policy in each unit. Most mature designs use a hybrid (platform/workloads at top, then environment).

10. How deep can a management-group hierarchy be, and how deep should it be? Up to 6 levels below the root group. It should be 2–3 — shallow trees keep inheritance reasonable; depth past three rarely earns its complexity.

11. How do you find out why a subscription is enforcing a policy it doesn’t define? Walk up the tree. List policy assignments at the subscription scope and read the scope field — an inherited one shows a management-group scope. For RBAC, use az role assignment list --include-inherited.

12. Why might managing the tenant root group fail even for a Global Administrator? Root-group management requires elevating access first — a deliberate safety feature so the most powerful node can’t be modified by default. An admin enables access elevation once before assigning policy/RBAC at the root.

Quick check

  1. A policy is assigned at a top-level management group. Does a subscription created next month under that group inherit it?
  2. Can a resource group “turn off” a Deny policy it inherited from a management group three levels up?
  3. You need the platform team to read every subscription, including future ones, with one action. Where do you assign Reader?
  4. How many parent management groups can a single subscription have?
  5. You want strict prod guardrails but loose dev rules for the same team. Do you split the tree by team or by environment?

Answers

  1. Yes. Inheritance is automatic and forward-looking — any subscription placed under that group inherits the assignment, including ones created after the policy was set. That is the entire value proposition.
  2. No. Inheritance cannot be cancelled at a lower scope. The deny holds; the only sanctioned carve-out is a scoped policy exemption, created deliberately at the subscription or resource group.
  3. At the tenant root group. A single Reader assignment there covers every current subscription and automatically extends to any added later — no per-subscription grants, no drift.
  4. Exactly one. A subscription has a single parent management group at any time, which is why you choose one axis for the tree and use RBAC/policy scoping for the other.
  5. By environment. Guardrails differ by environment, so a prod group and a non-prod group let you scope the strict policy to prod only. Keep the team together via RBAC scope rather than adding a second tree axis.

Glossary

Next steps

AzureManagement GroupsGovernanceAzure PolicyRBACLanding ZonesResource HierarchyAZ-104
Need this built for real?

Vinod is a Senior Cloud Architect (22+ yrs) — available for Azure / AWS / GCP architecture, landing zones, and migrations.

Work with me

Comments

Keep Reading