Cloud & infrastructure

A practical Azure landing zone for small and mid-size companies

Set up Azure management groups, subscriptions, hub-and-spoke networking, Azure Policy, RBAC and budgets the right way from day one, scaled down from Microsoft's landing zone architecture.

12 min read
On this page

A practical Azure landing zone for a small or mid-size company is a scaled-down version of Microsoft's reference architecture: an intermediate root management group under the tenant root, with Platform, Landing zones (Corp and Online), Sandbox and Decommissioned beneath it; one platform subscription that holds the hub network, VPN gateway and Log Analytics workspace; and separate subscriptions per workload and environment as spokes. Governance comes from a few Azure Policy assignments at management group scope, Azure RBAC granted to groups at subscription scope, a default management group for new subscriptions, and budgets on every subscription. Build it before the first workload, because moving resources between subscriptions later is harder than starting right.

Who this is for and what you will have

This guide is for IT teams of a few people who own Azure end to end, often alongside Microsoft 365, and who are about to move their first servers or applications into Azure or tidy up a subscription that grew without a plan. It follows the Cloud Adoption Framework (CAF) recommendations and uses the deviations Microsoft itself describes for smaller teams. At the end you will have:

  • A management group hierarchy that matches the CAF reference and can grow into it.
  • A subscription layout separating shared platform resources from workloads.
  • A hub-and-spoke network with a clean IP plan, ready for site-to-site VPN.
  • Baseline guardrails: allowed regions, required tags, protected hierarchy settings.
  • Access granted through groups, with budgets and alerts on every subscription.

What to keep and what to simplify

The full Azure landing zone separates Security, Management, Connectivity and Identity into their own management groups and subscriptions, because large enterprises have different teams for each. If one small team manages everything, CAF's ISV landing zone guidance suggests considering a single Platform management group, and its minimal example keeps all platform components in one subscription.

ComponentFull referenceSmall or mid-size company
Intermediate root management groupYesYes
Platform child management groups (Security, Management, Connectivity, Identity)Yes, one subscription eachOne Platform management group, one platform subscription
Landing zones: Corp, Online, LocalYesCorp and Online; add Local only for Azure Local clusters
Sandbox and DecommissionedYesYes
Hub networkPer region, often Azure FirewallOne hub in your primary region; firewall when needed
DeploymentIaC acceleratorIaC accelerator or a scripted build like the one below

What you should not simplify away: management groups themselves, separate platform and workload subscriptions, and a non-overlapping IP plan. Microsoft notes that starting with one subscription for both shared services and workloads is possible, but you will face problems later because not all resource types can be moved between subscriptions.

Prerequisites

  • A Microsoft Entra tenant you'll use for Azure (normally the same tenant as Microsoft 365) and a billing agreement that can create several subscriptions.
  • Access to the tenant root management group. Nobody has it by default; a Global Administrator elevates access once and then assigns roles, such as Hierarchy Settings Administrator for the hierarchy settings, to the platform admins.
  • The Az PowerShell module, or Azure Cloud Shell.
  • An agreed list of Azure regions, a tagging standard (for example owner, costCenter, environment), and an IP address plan that doesn't overlap with your offices or other clouds.
  • Security groups in Microsoft Entra ID for platform admins and for each workload team.

Step 1: Build the management group hierarchy

Create an intermediate root under the tenant root group so you never assign anything directly at the tenant root. The first management group in a directory can take up to 15 minutes to create while the service initializes.

Connect-AzAccount
 
New-AzManagementGroup -GroupName 'contoso' -DisplayName 'Contoso'
$root = Get-AzManagementGroup -GroupName 'contoso'
 
foreach ($mg in 'contoso-platform','contoso-landingzones','contoso-sandbox','contoso-decommissioned') {
    New-AzManagementGroup -GroupName $mg -DisplayName $mg -ParentId $root.Id
}
 
$lz = Get-AzManagementGroup -GroupName 'contoso-landingzones'
New-AzManagementGroup -GroupName 'contoso-corp'   -DisplayName 'Corp'   -ParentId $lz.Id
New-AzManagementGroup -GroupName 'contoso-online' -DisplayName 'Online' -ParentId $lz.Id

The resulting structure is three levels deep, inside CAF's recommendation of no more than three to four levels:

Tenant Root Group
└── Contoso (intermediate root)
    ├── Platform            -> sub-platform-prod
    ├── Landing zones
    │   ├── Corp            -> sub-erp-prod, sub-erp-dev, sub-fileserver-prod
    │   └── Online          -> sub-website-prod
    ├── Sandbox             -> developer and test subscriptions
    └── Decommissioned      -> subscriptions being cancelled

Use the management group IDs carefully: the GroupName can't be changed later. Corp is for workloads that need private connectivity to your offices through the hub; Online is for workloads that face the internet directly or don't need a virtual network. Don't create management groups for production, test and development, or for regions; use separate subscriptions instead.

Step 2: Protect the hierarchy

Two hierarchy settings on the tenant root management group close common gaps:

  • Default management group for new subscriptions. By default, new subscriptions land under the tenant root, outside your policies. CAF recommends a dedicated default, and suggests the sandbox management group as a good candidate, especially when staff have Visual Studio subscriptions.
  • Require write permissions for creating new management groups. By default any user in the tenant can create management groups under the root.

In the Azure portal, open Management groups, select the root management group, select Settings, then Change default management group and turn on Permissions for creating new management groups. Azure PowerShell has no cmdlet for these settings, so Microsoft's sample calls the REST API:

$rootId    = (Get-AzContext).Tenant.Id
$defaultId = 'contoso-sandbox'
 
$body = @{
    properties = @{
        defaultManagementGroup               = "/providers/Microsoft.Management/managementGroups/$defaultId"
        requireAuthorizationForGroupCreation = $true
    }
} | ConvertTo-Json
 
$token = (Get-AzAccessToken).Token
$uri   = "https://management.azure.com/providers/Microsoft.Management/managementGroups/$rootId/settings/default?api-version=2020-05-01"
 
Invoke-RestMethod -Method Put -Uri $uri -Authentication Bearer -Token $token `
    -ContentType 'application/json' -Body $body

The root management group's ID is the same as the Microsoft Entra tenant ID. Current Az.Accounts versions return the token from Get-AzAccessToken as a SecureString, which is why the sample passes it to -Token (PowerShell 7) rather than building the header by hand.

Step 3: Create and place the subscriptions

Plan subscriptions per workload and per environment, plus one platform subscription:

SubscriptionManagement groupContents
sub-platform-prodPlatformHub virtual network, VPN gateway, optional Azure Firewall and Bastion, Log Analytics workspace, private DNS zones
sub-<workload>-prodCorp or OnlineProduction spoke network and workload resources
sub-<workload>-devCorp or OnlineNon-production copy of the same workload
sub-sandbox-<name>SandboxExperiments; no connectivity to production

Move existing subscriptions into place in the portal (Management groups > select the target > Add subscription) or with PowerShell:

New-AzManagementGroupSubscription -GroupId 'contoso-platform' -SubscriptionId '00000000-0000-0000-0000-000000000000'
New-AzManagementGroupSubscription -GroupId 'contoso-corp'     -SubscriptionId '11111111-1111-1111-1111-111111111111'

A subscription that moves inherits the access and policies of its new parent. Moving it needs write permission on the subscription, the current parent and the target parent, except when the root management group is the source or target. Changes can take up to 30 minutes to show because of Azure Resource Manager token and management group caching.

If you already have one subscription with everything in it, Microsoft's guidance for that scenario is to deploy the landing zone in parallel in the same tenant and phase workloads across, rather than restructuring the existing subscription in place. The existing subscription can be placed in the hierarchy and later moved to Decommissioned. For the migration planning side, see the enterprise Azure cloud migration playbook.

Step 4: Lay out the network

Use a hub-and-spoke topology, which CAF recommends and the landing zone reference architecture is built on. The hub lives in the platform subscription; each workload subscription gets its own spoke virtual network peered to the hub.

  • IP plan first. Address spaces must not overlap across your offices and Azure. Reserve a block for Azure as a whole, then carve a hub range and one range per spoke.
  • GatewaySubnet. If you'll connect offices, create a subnet named GatewaySubnet in the hub. The hub-spoke reference architecture recommends /26 or larger.
  • AzureFirewallSubnet. If you deploy Azure Firewall, it needs a subnet named AzureFirewallSubnet of at least /26. NSGs aren't supported on it.
  • Peering. For spokes to reach your offices through the hub gateway, set the hub side of each peering to allow gateway transit, set the spoke side to use the remote virtual network's gateway, and allow forwarded traffic on all peerings.
  • One hub per region. Connect only spokes from the same region to a hub.

Azure Firewall in the hub gives you central egress control and inspection, but you can start without it and add it when the first internet-facing or regulated workload arrives. DDoS Protection is recommended for perimeter virtual networks; weigh it against the size of your public footprint. When you're ready to connect the office, follow the Azure site-to-site VPN setup guide.

Step 5: Assign baseline policies

Assign policies at management group scope so every current and future subscription inherits them, and keep assignments at the intermediate root few and broad. A sensible starting set:

Policy (built-in display name)ScopePurpose
Allowed locationsIntermediate rootKeep resources in approved regions
Require a tag on resource groupsLanding zonesEvery resource group carries an owner or cost center
Your choice of network and security policiesCorpFor example, deny public IPs on network interfaces in private workloads

Assign Allowed locations with its listOfAllowedLocations parameter:

$scope  = '/providers/Microsoft.Management/managementGroups/contoso'
$policy = Get-AzPolicyDefinition -BuiltIn | Where-Object { $_.DisplayName -eq 'Allowed locations' }
 
New-AzPolicyAssignment -Name 'allowed-locations' -DisplayName 'Allowed locations' `
    -PolicyDefinition $policy -Scope $scope `
    -PolicyParameterObject @{ listOfAllowedLocations = @('westeurope','northeurope') }
 
$lzScope = '/providers/Microsoft.Management/managementGroups/contoso-landingzones'
$tag     = Get-AzPolicyDefinition -BuiltIn | Where-Object { $_.DisplayName -eq 'Require a tag on resource groups' }
 
New-AzPolicyAssignment -Name 'rg-require-costcenter' -DisplayName 'Require costCenter tag on resource groups' `
    -PolicyDefinition $tag -Scope $lzScope `
    -PolicyParameterObject @{ tagName = 'costCenter' }

For a policy you're unsure about, add -EnforcementMode DoNotEnforce first, review compliance, then switch to enforcement. Sandbox subscriptions should get a lighter policy set than Corp and Online.

Step 6: Grant access through groups

Assign Azure roles to Microsoft Entra groups, not individual users, at the narrowest scope that works. CAF's recommendations for the hierarchy are specific:

  • Don't give workload teams roles at management group scope. Assign them at the subscription or resource group they need.
  • Platform admins can hold roles at management group scope for day-to-day work, but control those assignments with Privileged Identity Management so they're active only when needed.
$appTeam = (Get-AzADGroup -DisplayName 'AZ-ERP-Contributors').Id
New-AzRoleAssignment -ObjectId $appTeam -RoleDefinitionName 'Contributor' `
    -Scope '/subscriptions/11111111-1111-1111-1111-111111111111'
 
$platform = (Get-AzADGroup -DisplayName 'AZ-Platform-Readers').Id
New-AzRoleAssignment -ObjectId $platform -RoleDefinitionName 'Reader' `
    -Scope '/providers/Microsoft.Management/managementGroups/contoso'

Protect the accounts that can change the hierarchy with phishing-resistant MFA and Conditional Access; the same identity controls that protect Microsoft 365 apply here.

Step 7: Budgets, logging and security baseline

  • Budgets. On each subscription, open Budgets and select Add. Set a monthly amount, then add actual-cost and forecasted-cost alerts at thresholds such as 80% and 100%, with an email recipient or an action group. Budgets notify but never stop resources. Cost data typically arrives within 8 to 24 hours and budgets are evaluated every 24 hours, and a new subscription can take up to 48 hours before every Cost Management feature is available.
  • Central logging. Create one Log Analytics workspace in the platform subscription and point diagnostic settings for the hub resources at it. Turn off log categories you don't use; Azure Firewall in particular can generate large volumes.
  • Defender for Cloud. Review its recommendations for every subscription so security posture is visible from the first deployment.

Verification

  • Get-AzManagementGroup -GroupId 'contoso' -Expand -Recurse shows the full tree with each subscription under the intended parent.
  • In the portal, the root management group's Settings show the sandbox group as default and the permission toggle on. Create a test subscription and confirm it lands in Sandbox.
  • Try to create a resource group without the required tag in a Corp subscription; the deployment is denied. Try a disallowed region; it's denied too.
  • Get-AzPolicyState -ManagementGroupName 'contoso' -Filter "policyAssignmentId eq '/providers/Microsoft.Management/managementGroups/contoso/providers/Microsoft.Authorization/policyAssignments/allowed-locations' and ComplianceState eq 'NonCompliant'" lists existing non-compliant resources to remediate. (-PolicyAssignmentName only works for assignments made at subscription or resource group scope, not management group scope.) Compliance results take some time to appear after assignment.
  • Each subscription shows a budget, and the hub peerings show Connected.

Troubleshooting

The default management group or permission toggle is greyed out. You're not on the root management group, or your account lacks Microsoft.Management/managementgroups/settings/write on it. Assign Hierarchy Settings Administrator at the root.

You can't move a subscription to Corp. You need write permission on the subscription, its current parent and the target. If your Owner role on the subscription is inherited from the current management group, you can only move it to a management group where you're also Owner.

A moved subscription doesn't appear under its new parent. Azure Resource Manager tokens and the management group cache last 30 minutes. Sign out and in, or wait.

A deployment fails with a policy denial. The error names the policy assignment. If the denial is legitimate, fix the template; if the workload genuinely needs an exception, use an exemption or a narrower -NotScope rather than loosening the policy for everyone.

A budget shows no data. New subscriptions can take up to 48 hours before Cost Management features work. Budget alerts are also missed if the subscriptions in a management group scope use different currencies.

Closing checklist

  • Intermediate root with Platform, Landing zones (Corp, Online), Sandbox and Decommissioned.
  • Default management group set to Sandbox; management group creation requires authorization.
  • One platform subscription; separate subscriptions per workload and environment.
  • Hub-and-spoke network with non-overlapping address space, GatewaySubnet and peering settings for gateway transit.
  • Allowed locations and required tags assigned at management group scope.
  • Roles assigned to groups at subscription scope; platform roles controlled through PIM.
  • Budgets with actual and forecast alerts on every subscription; central Log Analytics workspace.
  • A plan to move the build into the IaC accelerator when the team is ready.

References

Questions people ask

Does a small company need an Azure landing zone?

Yes, but not every component of the full reference architecture. Microsoft describes the platform landing zone as a management group hierarchy plus centralized resources as needed, and its ISV landing zone guidance includes a minimal example that keeps all platform components in one subscription.

Can I run everything in one Azure subscription?

Technically yes, but Microsoft's landing zone guidance warns that you will face challenges later when you need to move resources between subscriptions, because not every resource type can be moved. Separate platform and workload subscriptions from the start.

Should I create management groups for dev, test and production?

No. The Cloud Adoption Framework recommends against management groups per environment. Put development, test and production in separate subscriptions under the same management group instead.

Which landing zone deployment option should I use?

Microsoft recommends the Azure Landing Zones IaC accelerator with Bicep or Terraform Azure Verified Modules. The portal accelerator is an option if you have no infrastructure-as-code skills, but it is harder to update and version later.

AzureAzure Landing ZonesManagement GroupsAzure PolicyAzure RBAC
  1. Amazon S3 for Azure admins: secure buckets with IAM and bucket policies

    Map Amazon S3 buckets, IAM policies, bucket policies, Block Public Access and presigned URLs to Azure Blob Storage, Azure RBAC and SAS, then build a locked down bucket with the AWS CLI.

  2. Azure Blueprints Retirement: Move to Template Specs and Deployment Stacks

    Azure Blueprints retires on January 31, 2027. Export your definitions, rebuild them in Bicep, publish template specs and recreate blueprint locks with deployment stack deny settings.

  3. Azure Policy Tag Enforcement: Require, Inherit and Remediate Tags

    Enforce CostCenter and Owner tags with built-in Azure Policy definitions: deny untagged resource groups, inherit tags onto resources, and remediate existing resources with managed identities.