Azure Lesson 34 of 137

Azure Landing Zone: Resource Organization — Management Groups, Subscription Strategy, Naming & Resource Group Structure

In a nutshell

Imagine your entire Azure estate as one enormous filing cabinet for a company that never stops growing. Management groups are the drawers — a few big categories that set the rules for everything inside them. Subscriptions are the hanging folders in each drawer — the unit you budget, secure, and scale against. Resource groups are the individual files in each folder — things that live and die together. And tags are the coloured sticky labels on everything, the dots that let you pull “every Production, finance-owned resource across the whole cabinet” in one search and put a rupee figure next to it. Resource Organization is the design area where you decide the shape of that cabinet before you start stuffing things into it.

Why care? Because the shape is load-bearing. In Azure, a policy or an access rule placed on a drawer automatically applies to every folder and file inside it — that one mechanic, inheritance, is what lets a small platform team govern thousands of resources without touching each one by hand. Put the drawers, folders, and labels in the right places and Azure Policy, Defender for Cloud, Cost Management, and your deployment pipelines all “just work”. Get the shape wrong and you spend the next three years doing tenant-wide migrations to fix it — because, as you’ll see, many of these names and boundaries are effectively permanent.

This lesson is written to serve two readers at once: a newcomer who has never seen a management group, and an architect who wants the edge cases, quotas, and inheritance mechanics. Read the core sections for the what and why; read Going deeper for the internals, limits, and failure modes; do the Practice challenges to make it stick.

Level: Advanced · Time: ~57 min

Prerequisites

After this lesson you’ll be able to

Where this fits

The Azure Landing Zone (ALZ) conceptual architecture is split into eight design areas grouped into two themes: Environment design (the platform plumbing — Identity, Network Topology and Connectivity, Resource Organization) and Governance & operations (Security, Management, Governance, Platform Automation and DevOps, and the cross-cutting Azure Billing and Microsoft Entra Tenant decision). Resource Organization is part 3 of this series, and it is deliberately foundational: it decides the shape of your tenant — the management group tree that policy and RBAC hang off, the subscriptions that act as your primary unit of scale and isolation, and the naming and tagging conventions that make everything after it queryable, governable, and billable. Get this wrong and every later design area inherits the debt; get it right and Policy, Defender for Cloud, Cost Management, and your platform pipelines all snap into place.

Azure Landing Zone Design Areas — animated overview

The management group hierarchy

What it is

A management group (MG) is a container above the subscription level that lets you apply Azure Policy assignments, Azure RBAC role assignments, and (in some cases) Cost Management views to many subscriptions at once through inheritance. Every Entra tenant has a single, non-deletable Tenant Root Group whose ID equals the tenant ID. You can nest MGs up to six levels deep below root (excluding the root level and the subscription level), and a single MG can hold up to a large number of children, but depth — not width — is what bites you. A subscription can live in exactly one MG at a time; an MG can contain both child MGs and subscriptions.

The thing that makes MGs the load-bearing wall of the whole landing zone is policy and access inheritance: an assignment at a parent flows down to every descendant subscription and resource, and it cannot be broken by a child (a child can only add more restriction, never remove a parent’s Deny or weaken a parent’s RBAC deny assignment). This is exactly why the ALZ reference hierarchy exists — it is an opinionated tree designed so the right guardrails land at the right altitude.

The ALZ reference hierarchy

The Cloud Adoption Framework ships a canonical hierarchy. Under Tenant Root you create a single top-level MG — conventionally named with your org’s intermediate root prefix, e.g. Contoso or simply alz — and beneath it the archetype branches:

Tenant Root Group
└── Contoso  (intermediate / top-level management group)
    ├── Platform
    │   ├── Identity        (DC/Entra Domain Services, identity VMs)
    │   ├── Management       (Log Analytics, Automation, monitoring)
    │   └── Connectivity     (hub vNet, Azure Firewall, ExpressRoute, DNS)
    ├── Landing Zones
    │   ├── Corp             (internal apps, NO public ingress, hub-routed)
    │   └── Online           (internet-facing apps, public endpoints allowed)
    ├── Sandbox              (loose guardrails, fast experimentation)
    └── Decommissioned       (cancelled subs awaiting deletion, locked down)

Why each branch exists:

Management group Purpose Representative guardrails assigned here
Intermediate root (Contoso) The single place to apply org-wide, non-negotiable policy so the Tenant Root Group stays clean and ungoverned-by-default Allowed locations, required tags, deny classic resources, Defender for Cloud auto-provisioning, diagnostic-to-Log-Analytics
Platform Shared services the whole org consumes; tighter change control Stronger RBAC, no public IP exceptions, DDoS, key-vault purge protection
Platform/Identity Domain controllers, Entra Domain Services, identity infra Restrict NSG/UDR changes, deny public network on identity stores
Platform/Management Centralized Log Analytics workspace, Automation, monitoring Enforce diagnostic settings, retention floors
Platform/Connectivity Hub networking, Azure Firewall, ExpressRoute/VPN, private DNS zones Deny IP forwarding exceptions, enforce firewall in path
Landing Zones Where application teams’ subscriptions live Baseline app guardrails: encryption, private endpoints preferred, deny unmanaged disks
Landing Zones/Corp Apps with no public ingress, reachable only via hub Deny public IP on NICs, force routes through hub
Landing Zones/Online Apps that legitimately expose public endpoints Allow public IP but mandate WAF/Front Door, TLS minimums
Sandbox Innovation space, isolated from production guardrails Minimal deny set, budget caps, network isolation from hub
Decommissioned Holding pen for cancelled subscriptions Read-only/locked, blanket deny on new resource creation

How to do it well

Concrete artifacts, decisions, and tools

Subscription strategy and democratization

What it is

A subscription is the primary boundary for scale (quota/limits), billing, policy/RBAC inheritance, and blast-radius isolation in Azure. Resource Organization’s job is to define how you carve workloads into subscriptions and — critically — to democratize their creation: instead of a central team being a bottleneck that hand-builds every subscription, the platform team publishes a subscription vending process that hands application teams a fully-governed, network-connected, policy-compliant application landing zone subscription on demand, within guardrails.

Why it matters

Subscriptions are where Azure’s hard and soft limits apply (e.g. role assignments per subscription, resource groups, public IPs, regional vCPU quotas, route tables). Packing everything into one giant subscription means you hit ceilings, you can’t separate prod from non-prod blast radius, your cost reporting is muddy, and a single noisy team’s quota request can stall everyone. Conversely, a thoughtless explosion of subscriptions creates management sprawl. The ALZ answer is a repeatable unit — the application landing zone — plus a vending machine to mint them consistently.

Subscription design patterns

Pattern Boundary you get Best when
Per workload/application (recommended ALZ default) Clean cost, RBAC, and quota isolation per app Most application landing zones; one app’s family of environments
Per environment (Prod / Non-Prod separate subs) Strong prod blast-radius isolation; different policy strictness per stage Regulated workloads; when prod change control must differ sharply
Per business unit / domain Chargeback alignment, delegated ownership Decentralized orgs with strong BU autonomy
Per geography / data residency Data-sovereignty and locality enforcement Multinationals with residency law (EU, India, etc.)
Shared platform subscriptions One each for Connectivity, Management, Identity Always, for the Platform MG — keep platform out of app subs

The mainstream ALZ guidance: one subscription per application landing zone, and within it use resource groups or separate subscriptions per environment depending on isolation needs. Treat subscriptions as a unit of management and scale, not as something precious — they’re cheap to create and you should be willing to spin up many.

Democratization via subscription vending

Subscription vending is the productized flow that makes democratization real:

  1. A team submits a request (ServiceNow ticket, a PR to a repo, or a self-service portal form) with metadata: app name, owner, cost center, environment, required network connectivity, budget.
  2. An automated pipeline (the subscription vending Terraform/Bicep module, e.g. Azure/lz-vending) creates the subscription under the correct billing scope, places it in the correct management group (so it inherits guardrails the instant it exists), assigns RBAC (the app team gets Owner/Contributor scoped to their sub, not the platform), wires networking (peers the spoke vNet to the hub, registers DNS), applies budgets and tags, and registers required resource providers.
  3. The team receives a ready-to-use, compliant subscription — typically in minutes — with no standing elevated access to the platform.

This is the heart of democratization: application teams move at their own speed inside guardrails they cannot remove, and the platform team governs by policy-as-code rather than by gatekeeping tickets.

Concrete artifacts, decisions, and tools

Naming and tagging standards

What it is

A naming convention is a deterministic, documented scheme for how every Azure resource, resource group, subscription, and management group is named; a tagging strategy is the set of metadata key/value pairs attached to resources, resource groups, and subscriptions to carry information that the name can’t (or shouldn’t) — owner, cost center, environment, data classification, criticality. Together they are what turn a tenant from a pile of GUIDs into a queryable, billable, auditable system.

Why it matters

You cannot manage what you cannot identify. Names are largely immutable for many resource types (you can’t rename a storage account or a VM without recreating it), so the cost of getting naming wrong is rework at scale. Tags drive cost allocation/showback/chargeback in Cost Management, automation targeting (start/stop, backup policy selection), operational routing (who to page), and compliance reporting (which resources hold regulated data). Crucially, tags are not inherited by default — a resource does not automatically get its resource group’s tags — which is precisely why you enforce them with policy.

Designing the naming convention

Microsoft’s CAF recommends a component-based pattern. A practical, hyphen-delimited template:

<resource-type>-<workload/app>-<environment>-<region>-<instance>
Component Example token Notes
Resource type vm, st, rg, kv, vnet, pip, nsg, law Use the CAF abbreviation list; some types (storage, Key Vault) forbid hyphens and have length limits
Workload / app kvfin, payments Short, stable app code
Environment prod, dev, test, uat, sbx Pick a fixed, enumerated set
Region eus2, cin (Central India), weu Map Azure regions to short codes once, org-wide
Instance 001, 002 Zero-padded for sortability

Worked examples:

Resource Name
Resource group for the payments app, prod, Central India rg-payments-prod-cin-001
Storage account (no hyphens, ≤24 chars, globally unique, lowercase) stpaymentsprodcin001
Key Vault (3–24 chars, globally unique) kv-payments-prod-cin
Virtual network vnet-payments-prod-cin-001
Log Analytics workspace law-mgmt-prod-cin-001

Naming rules that save pain: respect per-type length and character constraints (the storage and Key Vault cases above), keep globally-unique names collision-resistant by including app+env+region, decide case policy (lowercase everywhere is safest), and avoid encoding things that change often (don’t bake a team’s name into an immutable resource — use a tag instead).

Designing the tagging strategy

Split tags into mandatory (policy-enforced) and optional/recommended:

Tag key Example value Class Purpose
Environment Production Mandatory Policy strictness, cost split
CostCenter FIN-4412 Mandatory Chargeback/showback in Cost Management
Owner payments-team@contoso.com Mandatory Operational contact / paging
Application payments-core Mandatory Group all resources of one app across RGs
DataClassification Confidential Mandatory Compliance, access reviews
Criticality Tier1 Recommended SLA, DR prioritization
ManagedBy terraform Recommended Distinguish IaC vs click-ops resources
ExpiresOn 2026-12-31 Recommended Sandbox/temp cleanup automation

How to enforce it — the part that actually matters

A standard nobody enforces is a wish. Use Azure Policy as the enforcement engine:

For naming, Azure Policy can’t do arbitrary regex on names natively for every type, so enforce naming through Modify/Deny on name patterns where supported, plus module-level enforcement in IaC (the Terraform/Bicep modules compute names from inputs so humans never type them) and pipeline validation (a CI check, e.g. the Azure naming module Azure/naming/azurerm, that fails the build on a non-conforming name).

Concrete artifacts, decisions, and tools

Resource group structure

What it is

A resource group (RG) is a logical container inside a subscription that holds related resources. Every resource lives in exactly one RG; an RG has its own region (metadata location, independent of where its resources sit), can hold resources from many regions, and is itself a scope for RBAC, Azure Policy, locks, and tags. RGs are the finest grain at which you delegate access and apply guardrails before you reach individual resources.

Why it matters

RG structure determines lifecycle blast radius (deleting an RG deletes everything in it), delegation (you can give a team Contributor on just one RG), policy/lock placement, and how cleanly your cost and resource inventory reads. Two anti-patterns dominate real tenants: the mega-RG (hundreds of unrelated resources in one bucket, impossible to delete or delegate safely) and the RG-per-resource sprawl (no logical grouping, RBAC nightmare). The structuring principle that resolves both: group by shared lifecycle, shared ownership, and shared region. If resources are created, updated, and deleted together by the same team, they belong together.

How to structure them well

Resource group Contents Rationale
rg-payments-prod-cin-app App Service / AKS workload, app config Deployed and scaled as a unit
rg-payments-prod-cin-data SQL, Cosmos, storage — stateful Different lifecycle (you rarely tear down data with the app); stricter locks
rg-payments-prod-cin-net vNet, NSGs, private endpoints, UDRs Networking changes on its own cadence; locked down
rg-payments-prod-cin-shared Key Vault, Log Analytics, managed identities Shared across tiers, longest lifecycle

Concrete artifacts, decisions, and tools

Going deeper

This is the section for the reader who already gets the concepts and wants the mechanics, the limits, and the sharp edges. Everything below is additive to the four core sections — think of it as “what the docs make you click through a dozen pages to assemble”.

The hierarchy as one inheritance spine

Line the four containers up and you have a single vertical spine down which two things flow — Azure Policy and Azure RBAC — from the top to every resource at the bottom:

Tenant Root Group             <- one per Entra tenant, its ID == the tenant ID
  └── management groups        <- up to 6 levels deep; policy + RBAC inherit down
        └── subscription        <- unit of scale / billing / blast radius
              └── resource group  <- unit of lifecycle / delegation / locks
                    └── resource     <- the thing that actually costs money

Everything in Resource Organization is really about placing controls at the right point on this spine so inheritance does the work for you.

How inheritance actually resolves

RBAC role assignments are additive and cumulative: a principal’s effective access at any scope is the union of every role assignment at that scope and every ancestor scope. There is no “override” and no “deny by inheritance” in ordinary RBAC — granting Reader at a management group and Contributor at a resource group inside it gives the user Contributor there, not the more restrictive of the two. The only way to subtract access is a deny assignment, a separate object that RBAC evaluates before role assignments and that always wins. You don’t create deny assignments directly from the access-control blade; they’re produced by Azure-managed scenarios — historically Azure Blueprints locks, and today Deployment Stacks “deny settings” (denyDelete / denyWriteAndDelete).

Azure Policy inherits the same way but with the opposite polarity: a Deny (or DeployIfNotExists, Modify, Audit) effect assigned at a parent MG applies to every descendant and cannot be loosened by a child — a child scope can only add more restriction. This asymmetry is the whole reason the ALZ tree exists: you place each guardrail at the highest altitude where it is universally true so it can’t be escaped, and you leave lower scopes free to add specifics.

Two consequences that trip people up:

Management group settings and limits that actually bite

Boundary Current limit / behaviour Why it matters
MG hierarchy depth 6 levels below the root (excludes root and the subscription level) Depth multiplies “which assignment wins?” reasoning; stay at 2–4 meaningful levels
MGs per tenant (directory) 10,000 Effectively unlimited for org design; you’ll never hit it
Parents per MG or subscription Exactly one The tree is strict; a sub can’t sit in two MGs to “share” policy
Hierarchies per tenant One You get a single governance tree — design it to serve every purpose
Role assignments per management group 500 Keep RBAC lean at MG scope; assign to groups, not individuals

Three tenant-level settings are the difference between a governed hierarchy and a leaky one:

The subscription as a boundary — what “unit of scale” really means

The core lesson calls a subscription the unit of scale, billing, and blast radius. Concretely, that’s because Azure’s limits and quotas apply per subscription (and often per region within it):

Per-subscription boundary Representative limit Cost of packing everything into one sub
Regional vCPU quota (per VM family) Quota you request per region + family One team’s scale-out starves everyone; you queue quota tickets
Azure role assignments 4,000 per subscription Big shared subs hit the ceiling; you literally cannot grant more access
Resource groups 980 per subscription Mega-subs run out of RGs
Blast radius a boundary, not a number A bad deploy, a compromised credential, or a runaway cost stays contained

Billing scope is the other subscription decision. A vended subscription is minted under a specific billing container — an EA enrollment account, an MCA billing profile / invoice section, or a CSP partner scope. That choice governs which cost rollups and management-group cost views you can build later, so decide it before you vend at scale, not after. Programmatic subscription creation (the engine under vending) goes through the EA or MCA billing APIs.

A representative subscription-vending request — the small file an app team submits, which the pipeline turns into a governed subscription — looks like this (IDs are placeholders):

# landing-zones/payments-prod.yaml — a subscription vending request (representative)
subscription:
  displayName: sub-payments-prod-cin
  managementGroup: Corp-IN-Central        # governed at birth via the target MG
  billingScope: /providers/Microsoft.Billing/billingAccounts/PLACEHOLDER/billingProfiles/PLACEHOLDER/invoiceSections/PLACEHOLDER
  workload: payments
  environment: prod
  tags:
    Environment: Production
    CostCenter: FIN-4412
    Owner: payments-team@contoso.com
    Application: payments-core
    DataClassification: Confidential
networking:
  hubResourceId: /subscriptions/PLACEHOLDER/resourceGroups/rg-hub-connectivity-prod-cin/providers/Microsoft.Network/virtualNetworks/vnet-hub-prod-cin
  spokeAddressSpace: 10.42.0.0/22
  peerToHub: true
budget:
  amount: 500000                          # INR per month
  currency: INR
  alertThresholds: [60, 90, 100]
rbac:
  - principalId: PLACEHOLDER              # payments-team Entra group object id
    roleDefinition: Owner
    scope: subscription                   # scoped to this sub only, never the platform

The point of a schema like this: the app team supplies intent (name, cost center, environment, budget), and the pipeline supplies governance (correct MG placement, hub peering, scoped RBAC) — so the team never touches the platform and never types a subscription ID.

Tagging: three different inheritance mechanisms (know which one you mean)

“Do tags inherit?” has three different answers, and mixing them up is where cost reports go wrong:

  1. Native Azure — no inheritance. A resource carries exactly the tags you put on it. A resource does not pick up its resource group’s or subscription’s tags. Full stop.
  2. Azure Policy Inherit a tag from the resource group/subscription (a Modify-effect policy) — this actually writes the tag onto the resource, at create/update time and, via a remediation task, onto the existing estate. Afterwards the resource genuinely carries CostCenter, visible in Resource Graph, exports, and every downstream tool.
  3. Cost Management “tag inheritance” (a billing-scope setting) — this applies subscription/RG tags to usage records at reporting time only; it does not modify the resource. Turn it on and cost views split by CostCenter even for resources that never carried the tag; turn it off and the resource is untouched.

Use (2) when downstream systems — automation, Resource Graph queries, exports — must see the tag on the resource. Use (3) when you only need clean cost allocation and don’t want Policy rewriting thousands of resources. They’re frequently used together.

Limits and edges: 50 tags per resource, resource group, and subscription; tag name ≤ 512 characters (128 for storage accounts) and value ≤ 256 characters; not every resource type supports tags, and a handful of resources that don’t emit per-resource usage won’t carry tags into cost at all.

Showback vs chargeback is the reason all this rigour pays off. Showback = you report each business unit’s spend for visibility, but no money moves. Chargeback = you actually bill it back against their budget. Both rest on the same foundation — mandatory, clean CostCenter/Application tags — but chargeback raises the stakes on tag accuracy, which is exactly why chargeback shops enforce tags with a Deny-at-create policy plus remediation rather than trusting good intentions.

Naming: what Policy can and can’t enforce

Azure Policy can evaluate a resource’s name field, but only with pattern operators — like/notLike (wildcards * and ?) and match/matchInsensitive (a positional pattern where # = a digit, ? = a letter, and other characters are literal). That’s enough to enforce a required prefix or a rough shape; it is not arbitrary regular expressions. So real naming enforcement is layered:

And never forget naming’s cruel constraint — immutability. Worth pinning up:

Resource type Length Allowed characters Uniqueness Renameable?
Storage account 3–24 lowercase letters + digits only global No — recreate
Key Vault 3–24 alphanumerics + hyphens, start with a letter global No — recreate
Resource group 1–90 alphanumerics, _, (, ), -, . (not ending in .) per subscription No — recreate
Virtual machine 1–15 (Win) / 1–64 (Linux) letters, digits, hyphens (Win: not all-numeric) per resource group No — recreate
Virtual network 2–64 alphanumerics, _, -, . per resource group No — recreate

CAF publishes a recommended-abbreviations table (e.g. rg, vnet, snet, nsg, kv, st, vm, pip) — adopt it verbatim rather than inventing your own so every engineer and every tool reads names the same way. One wrinkle worth flagging: CAF’s own token for a Log Analytics workspace is log, whereas law (used in the naming table above) is a widespread community variant — either is fine, but pick one and be consistent across the org.

Resource locks and moving resources — the operational reality

Two lock types, and they inherit downward:

Locks are not RBAC — they apply to everyone regardless of role, and they override the corresponding RBAC action (an Owner cannot delete a CanNotDelete-locked resource without removing the lock first). Setting or removing a lock needs Microsoft.Authorization/locks/*, which Owner and User Access Administrator hold but Contributor does not.

Moving resources is the escape hatch when your grouping turns out wrong:

Tooling and version caveats (2026)

Real-world enterprise scenario

Helios Financial Group is a fictional pan-India digital lender with ~1,400 employees, a regulated workload profile (RBI data-localization obligations), and 60+ application teams migrating from a single sprawling “everything” subscription into Azure properly. Their CCoE adopts the ALZ Terraform accelerator and works the Resource Organization design area end to end.

Management group hierarchy. They deploy an intermediate root MG helios under Tenant Root, leaving Tenant Root assignment-free except for break-glass exclusions. Under helios: Platform (with Identity, Management, Connectivity), Landing Zones (with Corp and Online), Sandbox, and Decommissioned. Because RBI residency matters, they add geo sub-tiers under Landing Zones/CorpCorp-IN-Central and Corp-IN-South — to pin an Allowed locations policy (centralindia, southindia) at exactly the right altitude. They set the default management group to a Quarantine MG so any subscription created outside vending lands locked-down until reviewed. Artifact: a 6-node MG diagram and a policy-assignment matrix showing the Azure Security Benchmark initiative + 11 custom ALZ policies assigned at helios, residency policy at the geo tiers, and Deny public IP at Corp.

Subscription strategy and democratization. Helios chooses one subscription per application landing zone, with separate Prod and Non-Prod subscriptions for any Tier-1 app (blast-radius isolation that RBI auditors like). Platform gets three dedicated subs (Connectivity, Management, Identity). They stand up subscription vending with Azure/lz-vending: a team opens a PR to a landing-zones repo with a small YAML (app name, cost center, environment, criticality, residency, budget). The pipeline mints the subscription under their MCA invoice section, drops it into Corp-IN-Central or Online, peers its spoke vNet to the regional hub (Azure Firewall + ExpressRoute), registers private DNS, assigns the app team Owner scoped to that subscription only (platform access stays behind Entra PIM), and sets a ₹-denominated budget with action-group alerts at 60/90/100%. Outcome: a previously 3-week, ticket-driven subscription request drops to under 20 minutes, fully compliant, with zero standing platform access for app teams.

Naming and tagging standards. They publish <type>-<app>-<env>-<region>-<instance> with cin/sin region codes and a fixed env set (prod/uat/dev/sbx). Examples in their standard: rg-collections-prod-cin-data, stcollectionsprodcin001, kv-collections-prod-cin. Five mandatory tagsEnvironment, CostCenter, Owner, Application, DataClassification — are enforced by a tagging Azure Policy initiative assigned at helios: Deny on missing tags at create, plus Modify/inherit policies so resources inherit CostCenter and Environment from their RG (since tags don’t inherit natively), backed by remediation tasks that tagged 14,000 pre-existing resources. A CI linter using Azure/naming fails any PR with a non-conforming name. Cost Management is then sliced by CostCenter and Application for monthly showback to each business unit.

Resource group structure. Inside each app subscription the vending baseline seeds four RGs — -app, -data, -net, -shared — with CanNotDelete locks on -data, -net, and -shared. The collections DBA team gets Contributor on *-data only. Platform RGs (rg-hub-connectivity-prod-cin, rg-mgmt-logs-prod-cin) live in the platform subs.

Measurable outcome after one quarter: 47 application landing zones vended (target was 40); 100% mandatory-tag compliance on new resources and 96% across the legacy estate (audited live via Azure Resource Graph KQL); subscription provisioning lead time down ~99% (3 weeks → 20 min); first accurate per-business-unit Azure showback report produced; zero residency-policy violations because Allowed locations is pinned at the geo MG tier and inherited everywhere beneath.

Deliverables & checklist

Common pitfalls

  1. Mirroring the org chart in the management group tree. Departments reorganize constantly; your governance tree shouldn’t. Group MGs by guardrail similarity (what policy/RBAC a workload needs), not by who reports to whom — otherwise the next reorg triggers a tenant-wide MG migration.
  2. Assigning policy at the Tenant Root Group. Anything at root is inescapable and hits break-glass accounts; it also makes the root a single point of governance failure. Put org-wide policy at the intermediate root MG and keep Tenant Root clean.
  3. Centralized subscription creation as a manual bottleneck. Hand-building subscriptions via tickets kills cloud velocity and tempts teams into shadow IT. Productize it with subscription vending so teams self-serve inside guardrails they can’t remove.
  4. Assuming tags inherit. Resources do not inherit their resource group’s or subscription’s tags by default, so cost reports come out half-empty. Use Azure Policy Modify/inherit policies plus remediation tasks — and enforce mandatory tags with Deny at create time.
  5. Encoding volatile facts in immutable names. Many resource names can’t be changed without recreating the resource; baking a team name, owner, or cost center into the name guarantees rework. Keep names structural (type/app/env/region) and put changeable metadata in tags.
  6. Mega-resource-groups or RG-per-resource. Both break delegation and lifecycle management. Structure RGs by shared lifecycle, ownership, and region — separate stateful (-data), networking (-net), and shared (-shared) resources and lock the ones you can’t afford to lose.

Practice challenges

Work these top-to-bottom; each hides a solution with the why, not just the answer. They escalate from beginner to advanced.

1 — Place the workload (beginner). An internal HR app with no public endpoint, reachable only over the corporate network via the hub, is being onboarded. Which ALZ management group should its subscription land in, and name one guardrail it will inherit there.

<details><summary>Solution</summary>

Landing Zones/Corp. Corp is for apps with no public ingress, routed through the hub, so the subscription inherits a Deny public IP on NICs (or equivalent) guardrail plus the hub-routing/UDR policies. Why: Corp vs Online is the split by public-exposure guardrail, and HR-internal = Corp. Putting it in Online would wrongly permit public endpoints. </details>

2 — Make the name legal (beginner). A team proposes the storage account name st-Payments-Prod-CIN-001. It’s rejected at deploy. Give a compliant name and say why the original failed.

<details><summary>Solution</summary>

Compliant: stpaymentsprodcin001. Why: storage account names must be 3–24 characters, lowercase letters and digits only, no hyphens, globally unique. The original has hyphens and uppercase (both illegal). Hyphenated names like kv-payments-prod-cin are fine for Key Vaults, but never for storage accounts — the per-type constraint table is not optional. </details>

3 — Pick the subscription strategy (intermediate). A Tier-1 payments platform must keep production change-control and blast radius sharply separate from dev/test, and auditors want to see that separation. Per-app single subscription, or something else?

<details><summary>Solution</summary>

Use a per-application landing zone but split Prod and Non-Prod into separate subscriptions. Why: a single per-app sub gives clean cost/RBAC but not the hard prod/non-prod blast-radius and policy-strictness boundary a regulated Tier-1 workload needs. Separate subscriptions let you apply stricter policy and change-control to Prod and give auditors a clean isolation story. Lower-tier apps can stay single-sub with per-environment resource groups. </details>

4 — Choose the tag-inheritance mechanism (intermediate). Finance only needs the monthly cost split by CostCenter; they explicitly do not want Azure Policy rewriting tags onto thousands of resources. What do you turn on?

<details><summary>Solution</summary>

Enable Cost Management “tag inheritance” at the billing/subscription scope. Why: it applies the subscription/RG CostCenter tag to usage records at reporting time only, giving clean cost views without modifying any resource — exactly Finance’s ask. If automation or Resource Graph later needed to see the tag on the resource itself, you’d instead use the Azure Policy Inherit a tag from the resource group (Modify) approach. </details>

5 — Pin residency at the right altitude (advanced). A multinational must guarantee that all Corp workloads for its India entity deploy only to centralindia/southindia. The guarantee must be inescapable for those teams but must not constrain teams in other regions. Where do you assign the Allowed locations policy, and why not higher or lower?

<details><summary>Solution</summary>

Create a geo sub-tier under Corp (e.g. Corp-IN) and assign Allowed locations (centralindia,southindia) at that geo MG. Why: assigning at the intermediate root or Corp would wrongly restrict every region’s teams; assigning at each subscription is unenforceable drift (teams could deviate, and it’s N places to maintain). The geo MG is the highest altitude where the rule is universally true, so every India subscription beneath inherits it and no child can loosen it. </details>

6 — Debug the lock / RBAC puzzle (advanced). An Owner on rg-payments-prod-cin-data suddenly cannot delete a storage account there, and a separate app can no longer list that account’s keys. Both started right after a “safety” change. What happened, and how do you fix it without weakening safety?

<details><summary>Solution</summary>

Someone applied resource locks. A CanNotDelete lock blocks even an Owner from deleting until the lock is removed (locks override RBAC), and a ReadOnly lock blocks list-keys because that call is a POST/write — breaking key-based auth. Confirm: the RG’s Locks blade / az lock list. Fix without weakening: keep CanNotDelete on the data RG (that’s the intended guard), but replace the ReadOnly lock with CanNotDelete so deletion is still blocked while key-listing and normal operations work — or move the app to managed-identity / RBAC data-plane auth so it never needs account keys at all. </details>

Common beginner mistakes

These are misconceptions, not error messages — the wrong mental model and the right one. (They’re distinct from the architect-level Common pitfalls above.)

“A management group is just a bigger resource group.” No. A resource group holds resources; a management group holds subscriptions and other management groups — never resources directly. Its entire job is to be a scope you attach Policy and RBAC to so they inherit to everything beneath. Right model: RGs are the bottom of the tree (lifecycle grouping), MGs are the top (governance grouping) — they are not two sizes of the same thing.

“A resource group lives in one region, so everything in it runs there.” No. An RG’s location is metadata — where the group’s own record and deployment data live. The resources inside can be in any regions; an RG in eastus can happily hold a VM in centralindia. Right model: pick the RG region for the group’s metadata/residency, and set each resource’s region independently.

“If the naming convention changes, I’ll just rename things later.” Usually you can’t. Many resource names are immutable — you can’t rename a storage account, Key Vault, or VM; you delete and recreate (with data migration and downtime). Right model: treat names as write-once, keep only structural, stable facts in them (type/app/env/region), and push anything changeable into tags.

“Deleting a resource group is no big deal — I’ll just recreate it.” An RG delete is a cascading, irreversible delete of every resource inside it. There is no recycle bin for most resources. Right model: the RG is your lifecycle blast-radius boundary — group things that should die together, and put a CanNotDelete lock on any RG holding data, networking, or shared services.

“More management-group levels means tighter governance.” No — depth mostly adds confusion. Every extra level multiplies the “which assignment wins?” reasoning and slows propagation without making any single guardrail stronger. Right model: 2–4 meaningful levels is plenty; add a level only when a distinct set of guardrails genuinely applies there (like a geo-residency tier).

“A subscription is just how Azure bills me.” Billing is one of four jobs. A subscription is also your primary boundary for scale/quota (limits apply per subscription), RBAC/policy inheritance, and blast radius (isolation of failure, compromise, and cost). Right model: choose subscription boundaries for isolation and scale first — clean billing falls out of the same decision.

Glossary

What’s next

With the tenant’s shape established, part 4 of the Azure Landing Zone Design Areas turns to Security — the Defender for Cloud, encryption, secrets, and zero-trust controls you assign onto the very management group hierarchy and subscriptions you just built.

AzureLanding ZoneResource OrganizationEnterprise
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