Skip to main content

Azure Landing Zones

What are Azure Landing Zones?

Azure Landing Zones are pre-configured, scalable, and secure Azure environments designed to accelerate cloud adoption while enforcing governance, security, and operational best practices from day one.

Think of a landing zone as the foundation for your Azure environment—like utilities and infrastructure for a building before tenants move in.

Core Components:

┌─────────────────────────────────────────────────────────────┐
│ Azure Landing Zone Architecture │
└─────────────────────────────────────────────────────────────┘

Management Group Hierarchy

┌────────────────────────────────────────────────────────┐
│ Tenant Root Group │
│ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ Platform Landing Zone │ │
│ │ ├── Management (Logs, Monitoring, Backup) │ │
│ │ ├── Connectivity (Hubs, VPN, ExpressRoute) │ │
│ │ └── Identity (AD DS, Bastion) │ │
│ └──────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ Application Landing Zones │ │
│ │ ├── Corp (On-prem connectivity required) │ │
│ │ ├── Online (Internet-facing workloads) │ │
│ │ └── Sandbox (Isolated experimentation) │ │
│ └──────────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────────┘

Two Types:

TypePurposeExamples
Platform Landing ZoneShared services for entire organizationAzure Monitor, VPN Gateway, Azure AD
Application Landing ZoneWorkload-specific environmentWeb app resources, database, storage

Why Use Azure Landing Zones?

Without Landing Zones

❌ Each team builds infrastructure differently
❌ Security configurations inconsistent
❌ No centralized logging or monitoring
❌ Compliance violations discovered late
❌ High operational overhead
❌ Shadow IT and sprawl

With Landing Zones

Consistent Security: Azure Policy enforces standards automatically
Faster Onboarding: Teams get pre-configured subscriptions in minutes
Built-in Governance: Compliance from day one
Centralized Operations: Single pane of glass for monitoring
Cost Controls: Budget alerts and tagging enforced
Hybrid Connectivity: Hub-and-spoke networking ready

When to Use Landing Zones

✅ Use Landing Zones When:

  • Multi-team organization: 3+ teams deploying to Azure
  • Regulated industry: Need compliance (HIPAA, PCI-DSS, FedRAMP)
  • Hybrid cloud: Connecting on-premises to Azure
  • Growth trajectory: Expecting rapid Azure adoption
  • Governance requirements: Need centralized policy enforcement
  • Enterprise scale: 10+ subscriptions planned

⚠️ Consider Alternatives When:

  • Single small app: One team, one subscription
  • Proof of concept: Short-term experimentation
  • Greenfield startup: No existing infrastructure
  • Limited Azure use: Not planning to expand

Platform Landing Zone

The platform landing zone provides shared services for the entire organization.

Core Components

1. Management

Purpose: Centralized monitoring, logging, and operational tooling

Key Resources:

# Log Analytics Workspace
resource "azurerm_log_analytics_workspace" "platform" {
name = "law-platform-prod"
location = "eastus"
resource_group_name = "rg-platform-management-prod"
sku = "PerGB2018"
retention_in_days = 90

tags = {
Environment = "Production"
ManagedBy = "Platform Team"
}
}

# Azure Monitor (automatic)

# Automation Account
resource "azurerm_automation_account" "platform" {
name = "aa-platform-prod"
location = "eastus"
resource_group_name = "rg-platform-management-prod"
sku_name = "Basic"
}

What it Provides:

  • Centralized logging (all subscriptions send logs here)
  • Azure Monitor workbooks and dashboards
  • Update Management for VMs
  • Backup vaults
  • Security Center configuration

2. Connectivity

Purpose: Hub-and-spoke network topology for hybrid connectivity

Hub VNet Architecture:

┌─────────────────────────────────────────────────────┐
│ Hub VNet (10.0.0.0/16) │
│ │
│ ┌────────────────┐ ┌────────────────┐ │
│ │ VPN Gateway │ │ ExpressRoute │ │
│ │ Subnet │ │ Subnet │ │
│ │ 10.0.1.0/24 │ │ 10.0.2.0/24 │ │
│ └────────────────┘ └────────────────┘ │
│ │
│ ┌────────────────────────────────────┐ │
│ │ Azure Firewall Subnet │ │
│ │ 10.0.3.0/26 (must be /26) │ │
│ └────────────────────────────────────┘ │
│ │
│ ┌────────────────────────────────────┐ │
│ │ Azure Bastion Subnet │ │
│ │ 10.0.4.0/26 (must be /26) │ │
│ └────────────────────────────────────┘ │
└─────────────────────────────────────────────────────┘
│ │ │
│ │ │
▼ ▼ ▼
┌─────────┐ ┌─────────┐ ┌─────────┐
│ Spoke 1 │ │ Spoke 2 │ │ Spoke N │
│ VNet │ │ VNet │ │ VNet │
└─────────┘ └─────────┘ └─────────┘

Terraform Example:

# Hub VNet
resource "azurerm_virtual_network" "hub" {
name = "vnet-hub-prod"
address_space = ["10.0.0.0/16"]
location = "eastus"
resource_group_name = "rg-platform-connectivity-prod"
}

# Azure Firewall Subnet
resource "azurerm_subnet" "firewall" {
name = "AzureFirewallSubnet" # Name is mandatory
resource_group_name = azurerm_virtual_network.hub.resource_group_name
virtual_network_name = azurerm_virtual_network.hub.name
address_prefixes = ["10.0.3.0/26"]
}

# Azure Firewall
resource "azurerm_firewall" "hub" {
name = "fw-hub-prod"
location = "eastus"
resource_group_name = "rg-platform-connectivity-prod"
sku_name = "AZFW_VNet"
sku_tier = "Standard"

ip_configuration {
name = "configuration"
subnet_id = azurerm_subnet.firewall.id
public_ip_address_id = azurerm_public_ip.firewall.id
}
}

What it Provides:

  • Centralized internet egress via Azure Firewall
  • VPN or ExpressRoute for on-premises connectivity
  • Azure Bastion for secure VM access
  • Network security managed centrally

3. Identity

Purpose: Centralized identity and access management

Key Resources:

  • Azure AD Domain Services: Managed AD for legacy apps
  • Jump Box / Bastion: Secure access to Azure resources
  • Privileged Identity Management (PIM): Just-in-time admin access

Example:

# Azure AD Domain Services
resource "azurerm_active_directory_domain_service" "platform" {
name = "platform.example.com"
location = "eastus"
resource_group_name = "rg-platform-identity-prod"

domain_name = "platform.example.com"
sku = "Standard"
filtered_sync_enabled = false

initial_replica_set {
subnet_id = azurerm_subnet.adds.id
}
}

Application Landing Zones

Application landing zones are workload-specific subscriptions for teams to deploy applications.

Types of Application Landing Zones

1. Corp-Connected Landing Zones

For: Applications requiring on-premises connectivity

Characteristics:

  • VNet peered to hub VNet
  • Access to ExpressRoute/VPN
  • Subject to corporate network policies
  • Routed through Azure Firewall

Network Topology:

# Spoke VNet (Corp-connected)
resource "azurerm_virtual_network" "spoke" {
name = "vnet-app1-prod"
address_space = ["10.1.0.0/16"]
location = "eastus"
resource_group_name = "rg-app1-prod"
}

# VNet Peering to Hub
resource "azurerm_virtual_network_peering" "spoke_to_hub" {
name = "peer-app1-to-hub"
resource_group_name = azurerm_virtual_network.spoke.resource_group_name
virtual_network_name = azurerm_virtual_network.spoke.name
remote_virtual_network_id = data.azurerm_virtual_network.hub.id

allow_forwarded_traffic = true
allow_gateway_transit = false
use_remote_gateways = true # Use hub's VPN gateway
}

Use Cases:

  • Enterprise web applications
  • Databases needing on-prem data
  • Line-of-business applications
  • Lift-and-shift migrations

2. Online Landing Zones

For: Internet-facing applications with no on-premises connectivity

Characteristics:

  • No VNet peering to hub
  • Direct internet access
  • More relaxed network policies
  • Ideal for SaaS applications

Example:

# Standalone VNet (Online)
resource "azurerm_virtual_network" "online" {
name = "vnet-webapp-prod"
address_space = ["10.10.0.0/16"]
location = "eastus"
resource_group_name = "rg-webapp-prod"
}

# No peering to hub

Use Cases:

  • Public-facing websites
  • Mobile app backends
  • SaaS products
  • APIs for external customers

3. Sandbox Landing Zones

For: Experimentation, training, and development

Characteristics:

  • Isolated from production
  • Relaxed governance (no policy enforcement)
  • Auto-deletion policies (resources older than 30 days)
  • Limited Azure quotas

Policy Example:

{
"properties": {
"displayName": "Auto-delete resources older than 30 days",
"policyRule": {
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.Compute/virtualMachines"
},
{
"field": "tags['CreatedDate']",
"less": "[addDays(utcNow(), -30)]"
}
]
},
"then": {
"effect": "delete"
}
}
}
}

Use Cases:

  • Developer learning
  • Proof of concepts
  • Security testing
  • Training environments

Application Landing Zone Architecture Patterns

Pattern 1: App Service Environment

Application Landing Zone (Subscription)

├── Resource Group: Networking
│ ├── VNet (10.1.0.0/16)
│ ├── App Service Subnet (delegated)
│ └── Private Endpoints Subnet

├── Resource Group: Compute
│ ├── App Service Plan (Isolated SKU)
│ ├── App Service Environment v3
│ └── Function Apps

├── Resource Group: Data
│ ├── SQL Database (Private Endpoint)
│ └── Storage Account (Private Endpoint)

└── Resource Group: Security
├── Key Vault (Private Endpoint)
└── Application Gateway (WAF)

Pattern 2: Azure Kubernetes Service (AKS)

Application Landing Zone (Subscription)

├── Resource Group: Networking
│ ├── VNet (10.2.0.0/16)
│ ├── AKS Subnet (/22)
│ ├── Application Gateway Subnet
│ └── Private Endpoints Subnet

├── Resource Group: Compute
│ └── AKS Cluster (Private)
│ ├── System Node Pool
│ └── User Node Pool

├── Resource Group: Data
│ ├── Azure Database for PostgreSQL
│ └── Azure Cache for Redis

└── Resource Group: Supporting Services
├── Container Registry (Private Endpoint)
├── Key Vault
└── Log Analytics Workspace

Management Group Hierarchy

Organize subscriptions with management groups to apply governance at scale:

Tenant Root Group

├── Platform
│ ├── Management (1 subscription)
│ ├── Connectivity (1 subscription)
│ └── Identity (1 subscription)

├── Landing Zones
│ ├── Corp
│ │ ├── Finance Apps (3 subscriptions)
│ │ └── HR Apps (2 subscriptions)
│ │
│ ├── Online
│ │ ├── Marketing Website (1 subscription)
│ │ └── Customer Portal (2 subscriptions)
│ │
│ └── Sandbox
│ └── Dev/Test (5 subscriptions)

└── Decommissioned
└── Legacy Apps (archived)

Apply Azure Policy at Management Group Level:

# Policy: Require specific tags
resource "azurerm_management_group_policy_assignment" "require_tags" {
name = "require-tags"
management_group_id = azurerm_management_group.landing_zones.id
policy_definition_id = azurerm_policy_definition.require_tags.id

parameters = jsonencode({
tagNames = {
value = ["Environment", "Owner", "CostCenter"]
}
})
}

Best Practices

1. Subscription Democratization

Principle: Treat subscriptions as units of management and scale, not scarcity

Do:

  • Give each application team their own subscription
  • Use subscriptions for blast radius isolation
  • Automate subscription provisioning (subscription vending)

Don't:

  • Share subscriptions across multiple teams
  • Manually create subscriptions
  • Use subscriptions as cost centers (use tags instead)

2. Policy-Driven Governance

Principle: Enforce compliance automatically, not manually

# Prevent public IP creation in production
resource "azurerm_policy_definition" "deny_public_ip" {
name = "deny-public-ip-creation"
policy_type = "Custom"
mode = "All"
display_name = "Deny Public IP Creation"

policy_rule = jsonencode({
if = {
field = "type"
equals = "Microsoft.Network/publicIPAddresses"
}
then = {
effect = "deny"
}
})
}

3. Hub-and-Spoke Networking

Do:

  • Centralize egress through Azure Firewall
  • Use VNet peering for spoke-to-hub connectivity
  • Route all traffic through hub for inspection

Don't:

  • Create individual VPN gateways per subscription
  • Allow direct internet access from spoke VNets
  • Peer spoke-to-spoke directly (use hub routing)

4. Separation of Duties

RoleResponsibilitiesManagement Group Scope
Platform TeamManage hub, connectivity, policiesPlatform
App TeamDeploy applications, manage resourcesApp Landing Zone
Security TeamDefine policies, audit complianceTenant Root
Finance TeamCost management, budgetsAll subscriptions

5. Tagging Strategy

Enforce tags via policy:

# Policy: Inherit tags from resource group
resource "azurerm_policy_definition" "inherit_tags" {
name = "inherit-tags-from-rg"
policy_type = "Custom"
mode = "Indexed"
display_name = "Inherit Tags from Resource Group"

policy_rule = jsonencode({
if = {
field = "[concat('tags[', parameters('tagName'), ']')]"
notEquals = "[resourceGroup().tags[parameters('tagName')]]"
}
then = {
effect = "modify"
details = {
operations = [{
operation = "addOrReplace"
field = "[concat('tags[', parameters('tagName'), ']')]"
value = "[resourceGroup().tags[parameters('tagName')]]"
}]
}
}
})
}

Required tags:

  • Environment: dev, staging, prod
  • Owner: Team email
  • CostCenter: Finance code
  • Application: App name
  • DataClassification: Public, Internal, Confidential

Deployment Approaches

Option 1: Azure Landing Zone Accelerator (Portal)

Best for: Getting started quickly, small organizations

  1. Go to: https://aka.ms/alz/portal
  2. Select deployment options:
    • Management groups
    • Hub networking
    • Identity
  3. Click Deploy

Pros: Fast, no code
Cons: Limited customization

Option 2: Terraform Module

Best for: Infrastructure as Code, customization, automation

# Use CAF Landing Zones Terraform Module
module "enterprise_scale" {
source = "Azure/caf-enterprise-scale/azurerm"
version = "~> 6.0"

default_location = "eastus"
root_parent_id = data.azurerm_client_config.current.tenant_id

deploy_management_resources = true
deploy_connectivity_resources = true
deploy_identity_resources = false

configure_management_resources = {
location = "eastus"
settings = {
log_analytics = {
retention_in_days = 90
}
}
}

configure_connectivity_resources = {
location = "eastus"
settings = {
hub_networks = [{
enabled = true
config = {
address_space = ["10.0.0.0/16"]
azure_firewall_enabled = true
azure_firewall_sku = "Standard"
vpn_gateway_enabled = false
expressroute_gateway_enabled = true
}
}]
}
}
}

Option 3: Bicep/ARM Templates

Best for: Azure-native approach, Azure DevOps integration

# Deploy using Azure Verified Modules
az deployment tenant create \
--name "landing-zone-deployment" \
--location "eastus" \
--template-file "main.bicep" \
--parameters "@parameters.json"

Common Pitfalls to Avoid

❌ 1. Skipping Landing Zones for Speed

Mistake: "We'll add governance later"

Impact: Technical debt, security vulnerabilities, costly refactoring

Solution: Start with lightweight landing zone, add policies incrementally

❌ 2. Over-Engineering Too Early

Mistake: Building complex landing zone for 2-person startup

Impact: Wasted time, maintenance burden

Solution: Match complexity to organization size (start simple)

❌ 3. Not Planning for Multi-Region

Mistake: Hard-coding location = "eastus" everywhere

Impact: Difficult to add disaster recovery

Solution: Use variables:

variable "primary_location" {
default = "eastus"
}

variable "secondary_location" {
default = "westus"
}

❌ 4. Tight Coupling Between Platform and Apps

Mistake: App teams depend on specific platform team resources

Impact: Platform changes break applications

Solution: Define clear contracts (e.g., "Hub VNet CIDR won't change")

❌ 5. Ignoring Subscription Limits

Issue: Azure has limits (e.g., 500 VNets per subscription)

Solution: Plan subscription topology early, monitor quotas