Azure Enterprise Architecture
How Azure is structured for enterprise work: the management group and subscription hierarchy, Entra ID and RBAC, Azure Policy guardrails, hub-and-spoke networking, and the failure modes teams hit.
This reference describes how to design and implement enterprise-scale systems on Azure using foundational architectural patterns, service selection criteria, and implementation constraints. It applies when building multi-tenant applications, compliance-sensitive workloads, or distributed systems requiring strong governance.
Core Patterns for Multi-Tenant Systems
Azure supports multiple tenant models through resource group organization and subscription isolation. The recommended approach uses a hierarchy of subscriptions grouped by business unit or application tier.
/
├── Platform
│ ├── Shared Services
│ └── Infrastructure
├── Applications
│ ├── Core
│ ├── Supporting
│ └── Legacy
└── Compliance
├── Audit
└── Governance
Each subscription should contain exactly one environment (dev, test, prod) to prevent cross-environment contamination. Subscription names must follow a strict format: org-[team]-[env]-[purpose] where purpose is limited to app, infra, data, or shared.
Resource Group Organization
Resource groups should be created with explicit naming conventions:
az group create \
--name rg-app-core-prod \
--location eastus \
--tags Environment=prod Team=core
All resources within a group must share the same lifecycle. The group name format is rg-[app]-[component]-[env]. For example, rg-web-api-prod for production web API resources.
Identity and Access Management
Azure Active Directory (AAD) integration uses standard OAuth 2.0 flows with JWT tokens. Applications must register in AAD using the Application Registration Portal, not through any proprietary UI.
Service Principals for Automation
Service principals require a client secret or certificate for authentication:
az ad sp create-for-rbac \
--name sp-automation \
--role Contributor \
--scopes /subscriptions/{subscription-id}/resourceGroups/rg-app-core-prod
The returned JSON contains appId and password. These credentials must be stored in a secret management system that supports rotation.
Role-Based Access Control
Roles are assigned at subscription, resource group, or resource scope. Assigning roles to groups requires creating an Azure AD group first:
az ad group create \
--display-name "Core Application Developers" \
--mail-nickname "core-devs"
Then assign the role using the group's object ID:
az role assignment create \
--assignee {group-object-id} \
--role "Contributor" \
--scope /subscriptions/{subscription-id}/resourceGroups/rg-app-core-prod
Network Architecture
Azure virtual networks (VNETs) use standard CIDR notation and do not support arbitrary IP ranges. Subnets must be defined with at least a /24 prefix for production environments.
VNET Peering
VNET peering connects networks using standard Azure network protocols:
az network vnet peering create \
--name peering-frontend-backend \
--resource-group rg-network-prod \
--vnet-name vn-frontend \
--remote-vnet vn-backend
Peering requires both sides to be in the same region or use global VNETs with cross-region connectivity.
Private Endpoints
Private endpoints create private IP addresses for Azure services:
az network private-endpoint create \
--name pe-redis \
--resource-group rg-app-core-prod \
--vnet-name vn-app \
--subnet subnet-app \
--private-connection-resource-id /subscriptions/{subscription-id}/resourceGroups/rg-data-prod/providers/Microsoft.Cache/Redis/mycache \
--group-id redis
Private endpoints require that the target service supports private linking. The endpoint's IP address becomes static within the subnet.
Storage Design
Azure Blob Storage uses standard HTTP REST APIs. Containers must be created with proper lifecycle policies for archival and deletion.
Data Lifecycle Management
Lifecycle rules are defined using standard JSON:
{
"rules": [
{
"name": "archive-old-logs",
"enabled": true,
"conditions": {
"lastModifiedBefore": "2023-01-01T00:00:00Z"
},
"actions": {
"tierToArchive": {
"daysAfterModification": 90
}
}
}
]
}
Storage Account Access
Storage accounts require either shared key authentication or OAuth tokens. SAS tokens are valid for up to 1 year:
az storage account generate-sas \
--account-name mystorageaccount \
--expiry 2024-01-01T00:00:00Z \
--permissions rwdlacup \
--resource-types o \
--services b
Monitoring and Observability
Azure Monitor uses standard HTTP endpoints for log ingestion. Metrics are collected automatically for most Azure services.
Log Analytics Workspace Setup
Create a workspace with specific retention settings:
az monitor log-analytics workspace create \
--name la-workspace-prod \
--resource-group rg-monitoring-prod \
--retention-days 90
Log Analytics workspaces must be linked to subscriptions for resource monitoring. The link requires a service principal with the appropriate permissions.
Alert Rules
Alert rules use standard REST API endpoints:
az monitor metrics-alert create \
--name alert-high-cpu \
--resource-group rg-app-core-prod \
--scopes /subscriptions/{subscription-id}/resourceGroups/rg-app-core-prod/providers/Microsoft.Compute/virtualMachines/myvm \
--condition "avg Percentage CPU > 80" \
--window-size 5m \
--evaluation-frequency 1m
Alerts must specify a time window and evaluation frequency. The system only evaluates conditions once per minute.
Governance and Compliance
Resource tags are required for all Azure resources. Tags follow a strict naming convention: Environment, Owner, Project, CostCenter.
Policy Definitions
Azure Policy uses standard JSON schema for definitions:
{
"mode": "All",
"policyRule": {
"if": {
"not": {
"field": "tags.Environment",
"in": ["dev", "test", "prod"]
}
},
"then": {
"effect": "deny"
}
}
}
Policies are assigned at scope levels using standard Azure Resource Manager API:
az policy assignment create \
--name policy-environment-tag \
--scope /subscriptions/{subscription-id}/resourceGroups/rg-app-core-prod \
--policy policy-environment-tag.json
Security Considerations
Network security groups (NSGs) must be explicitly configured for each subnet. Rules are applied in order, and the first matching rule determines action.
NSG Rule Creation
NSG rules require explicit priority numbers:
az network nsg rule create \
--nsg-name nsg-app \
--resource-group rg-network-prod \
--name allow-ssh \
--priority 100 \
--protocol Tcp \
--direction Inbound \
--source-address-prefixes 10.0.0.0/24 \
--destination-port-ranges 22
Rules with overlapping CIDR ranges must have unique priorities to prevent unexpected behavior.
Key Vault Integration
Secrets are stored using standard HTTP REST API:
az keyvault secret set \
--name db-password \
--value "supersecret123" \
--vault-name kv-app-secrets
Access policies use standard JSON format with permissions:
{
"objectId": "{principal-object-id}",
"permissions": {
"keys": ["get", "list"],
"secrets": ["get", "list"],
"certificates": ["get", "list"]
}
}
Failure Modes and Pitfalls
Subscription Limits
Each subscription has a hard limit of 800 resource groups. Exceeding this limit causes failures during resource creation with error code ResourceGroupQuotaExceeded.
Tagging Errors
Missing required tags results in policy denials with message:
The request was denied by the policy because the resource does not have the required tag(s).
Role Assignment Conflicts
Assigning conflicting roles to the same principal causes silent failures. The system logs the conflict but continues without error.
VNET Peering Failures
VNET peering fails when both networks use overlapping address spaces, resulting in InvalidVnetPeering errors.
Resource Naming Restrictions
Resource names must be between 1 and 80 characters, alphanumeric only. Invalid names produce InvalidResourceName errors during creation.
Monitoring Limitations
Log Analytics workspaces cannot be shared across subscriptions without manual configuration. This requires additional setup steps for cross-subscription monitoring.
The architecture described here focuses on standard Azure capabilities without relying on proprietary extensions or vendor-specific features. All operations use documented REST APIs, standard CLI commands, and well-defined configuration formats.
This page was rewritten on 16 October 2026. It replaced a templated version that was not specific to its own title. How these pages are written and checked. If anything here is wrong, tell us at [email protected] and we will correct it.