Skip to main content

Management Group Hierarchy

I spend a lot of time on management group design at the start of enterprise Azure engagements, because mistakes here are expensive to fix. Management groups are the attachment point for Azure Policy and RBAC at scale — getting the hierarchy wrong means policies apply where they shouldn't, or don't apply where they should, and untangling that after workloads are deployed is painful.

The baseline hierarchy

The Cloud Adoption Framework's hierarchy is a solid starting point and I use it as the default:

Tenant Root Group

├── Platform
│ ├── Management (Log Analytics, Backup, Azure Monitor)
│ ├── Connectivity (Hub VNets, Firewall, ExpressRoute, DNS)
│ └── Identity (AD DS, Bastion, PIM config)

├── Landing Zones
│ ├── Corp (workloads requiring on-premises connectivity)
│ ├── Online (internet-facing, no on-prem dependency)
│ └── Sandbox (isolated, relaxed governance, auto-expiry)

├── Decommissioned (subscriptions pending cleanup)

└── (optional custom groups — see below)

The value of this structure is the policy inheritance model. Policies assigned at Landing Zones apply to everything under it. Policies at Corp only apply to corp workloads. This makes it possible to enforce "all prod workloads route through the firewall" without writing per-subscription rules.

When to create a new management group

This comes up in every engagement. The question is usually: "should the data platform be in Corp or Online, or should it get its own group?"

My rule: create a new management group only when a distinct set of policies needs to apply to a set of subscriptions that would contradict the policies on siblings.

Practically, that means:

ScenarioMy recommendation
Data platform that needs on-prem connectivityPlace in Corp — same network policy applies
Data platform with specific data residency or compliance requirements (e.g., financial data partition)New management group under Landing Zones: Landing Zones/Corp/DataPlatform
SaaS product (internet-facing, no on-prem, but stricter egress controls than standard Online workloads)New management group: Landing Zones/Online/SaaS with additional deny policies
Development/test environments that mirror productionSubdirectory under the appropriate zone: treat dev as a landing zone class, not a separate hierarchy branch
Outsourced operations requiring separate RBAC scopeNew management group: Landing Zones/Managed with RBAC scoped to the outsourcing partner

The anti-pattern I see most often: creating a new management group for every team or every application. This produces a deep hierarchy that makes policy management harder, not easier. Subscriptions are the right unit for application isolation — management groups are structural, not operational.

Placing specialised workloads

Data platforms (Azure Synapse, Databricks, Azure Data Factory):

I typically place these in Corp if they need to pull from on-premises sources. If they're purely cloud-native (ingesting from cloud services only), they go in Online. If the organisation has specific regulatory requirements around data classification or data residency, I create a DataPlatform sub-group with policies enforcing those controls:

Landing Zones
└── Corp
└── DataPlatform ← additional policies: deny cross-region data movement,
enforce diagnostic retention, require CMK encryption

SaaS products:

SaaS products often need looser network controls than internal corporate apps (they serve external customers, they need to call external APIs), but they have their own security requirements (PCI-DSS if payments, GDPR for EU customers). I place them under Online and add a sub-group when the policy differences are significant enough:

Landing Zones
└── Online
└── SaaS ← additional policies: require WAF, deny non-compliant
cipher suites, enforce HTTPS, no inbound 0.0.0.0/0

Platform engineering SaaS tools (Terraform Cloud, Artifactory, GitHub Enterprise Server):

These don't belong in Landing Zones — they're platform tooling. I place them under Platform:

Platform
├── Management
├── Connectivity
├── Identity
└── Tooling ← CI/CD tooling, artifact management, developer tools

Policy assignment strategy by level

The hierarchy defines where policies live. Here's how I think about the right level for each type of control:

ControlAssign atReason
Require approved Azure regionsTenant Root Group or Landing ZonesNon-negotiable for all workloads
Require specific tags (Environment, Owner, CostCenter)Landing ZonesAll workloads, but sandbox may be exempt
Deny public IP creationCorpCorp workloads should be private; Online workloads may need public IPs
Enforce routing through hub firewallCorpCorp only — Online workloads route differently
Require CMK encryptionLanding Zones/DataPlatformData workloads only
Deny most resource types (sandbox isolation)SandboxRestrict what can be deployed in sandbox

Terraform setup

# Management group structure
resource "azurerm_management_group" "root" {
display_name = "Tenant Root"
}

resource "azurerm_management_group" "platform" {
display_name = "Platform"
parent_management_group_id = azurerm_management_group.root.id
}

resource "azurerm_management_group" "landing_zones" {
display_name = "Landing Zones"
parent_management_group_id = azurerm_management_group.root.id
}

resource "azurerm_management_group" "corp" {
display_name = "Corp"
parent_management_group_id = azurerm_management_group.landing_zones.id
}

resource "azurerm_management_group" "online" {
display_name = "Online"
parent_management_group_id = azurerm_management_group.landing_zones.id
}

resource "azurerm_management_group" "sandbox" {
display_name = "Sandbox"
parent_management_group_id = azurerm_management_group.landing_zones.id
}

resource "azurerm_management_group" "decommissioned" {
display_name = "Decommissioned"
parent_management_group_id = azurerm_management_group.root.id
}

# Move a subscription into a management group
resource "azurerm_management_group_subscription_association" "my_sub" {
management_group_id = azurerm_management_group.corp.id
subscription_id = "/subscriptions/${var.subscription_id}"
}

RBAC across management groups

Management groups are also the right scope for platform team RBAC. I assign broad roles high in the hierarchy and narrow roles low:

RoleScopeWho
OwnerPlatform management groupPlatform team only
ContributorLanding Zones (specific sub-group)Delegated delivery teams
ReaderTenant Root GroupSecurity and audit team
Cost Management ReaderTenant Root GroupFinance team

I never assign Owner at the tenant root — that's an emergency break-glass account only.