Theoretical Foundation: Manage Subscriptions
1. Initial Intuitionβ
Think of a large company with branches in several countries. Each branch has its own budget, its own bank accounts, its own spending limits. The headquarters can see everything, but each branch is an independent financial and administrative unit.
In Azure, a Subscription is exactly this unit: a contract with Microsoft that defines billing limits, resource limits, and an administrative perimeter. Everything you create in Azure exists within a subscription. It's the level where the invoice is generated, where resource quotas are defined, and where administrative limits are established.
Small organizations usually start with a single subscription and manage everything within it. Larger organizations often have dozens or hundreds of subscriptions, each representing a department, project, environment, or geographic region.
2. Contextβ
Where Subscriptions fit in the Azure hierarchyβ
The Subscription is the second level of the Azure hierarchy (below the Tenant and Management Groups, above Resource Groups). It's the fundamental billing boundary and the main container of resources.
Why Subscriptions exist as a separate unitβ
Subscriptions exist for three fundamental reasons:
1. Billing boundary: each subscription generates a separate invoice. This allows precise chargeback per department or project.
2. Scale boundary: each subscription has independent resource quotas (number of VMs, CPUs, public IPs, etc.). Separating into subscriptions prevents one project from exhausting the resources of the entire organization.
3. Access control boundary: allows teams to have complete autonomy within their subscription without affecting other subscriptions.
What depends on Subscriptionsβ
- Every Resource Group belongs to a subscription
- Resource quotas are per subscription
- Billing is per subscription
- RBAC, Policy, and Locks applied at subscription level inherit to all RGs and resources within
- Service Limits (quotas) are defined per subscription
3. Concept Constructionβ
3.1 Subscription Typesβ
Subscriptions are not all the same. The type determines the pricing model, limits, and available resources:
| Type | Description | Use case |
|---|---|---|
| Pay-As-You-Go | Pay for what you use, no commitment | Startups, variable projects |
| Enterprise Agreement (EA) | Multi-year contract with volume discounts | Large companies with predictable spending |
| Microsoft Customer Agreement (MCA) | Modern successor to EA, more flexible | Medium to large enterprises |
| Cloud Solution Provider (CSP) | Managed by Microsoft partner | Clients who purchase via reseller |
| Visual Studio / Dev/Test | Monthly credits for development | Individual developers, dev teams |
| Azure Free | Initial credit + free services for 12 months | Initial experimentation |
| Azure for Students | Credits for students | Education |
| Sponsored | Credits provided by Microsoft | Startups via specific programs |
3.2 Subscription and Azure AD Tenant Relationshipβ
This is one of the most important and frequently misunderstood distinctions:
Tenant is the Azure Active Directory instance. It's the organization's identity: where users, groups, and applications live.
Subscription trusts a Tenant for authentication. A subscription is associated with exactly one Tenant at a time, but a Tenant can have multiple subscriptions.
Critical implication: when you move a subscription to a different Tenant (process called transfer), all role assignments (RBAC) are lost, because users from the old Tenant don't exist in the new Tenant. The resources themselves are preserved, but access needs to be completely reconfigured.
3.3 Subscription ID and nameβ
Each subscription has:
- ID: unique and immutable GUID (ex:
xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx) - Name: readable string, editable, not globally unique
- State: Enabled, Disabled, Deleted, Warned, Past Due
The ID is the permanent identifier. The name can be changed without impact on resources. In scripts and automation, always use the ID, never the name.
3.4 Subscription Statesβ
Disabled state is critical: when a subscription becomes Disabled, resources within it become inaccessible (they are not immediately deleted). You have a 90-day period to re-enable before resources are permanently deleted. During this period, data is preserved but without access.
3.5 Service Limits and Quotasβ
Each subscription has limits (quotas) per resource type and per region. These limits exist to protect Microsoft's shared infrastructure and can be increased via request.
Examples of important default limits:
| Resource | Default limit | Maximum limit |
|---|---|---|
| VMs per region | 25,000 | Depends on VM type |
| Total vCPUs per subscription | 20 (pay-as-you-go) | Requestable |
| Resource Groups per subscription | 980 | 980 (fixed) |
| Role assignments per subscription | 4,000 | 4,000 (fixed) |
| Virtual Networks per subscription | 50 | 1,000 |
| Public IP addresses | 20 | Requestable |
| Storage Accounts per subscription | 250 | 250 per region |
vCPU limits are most frequently hit and most important to request increases before needing them.
3.6 Management Groupsβ
Management Groups are containers that organize multiple subscriptions in a hierarchy. They allow applying governance (RBAC, Policy, Locks) at scale over a set of subscriptions.
The pattern above is Microsoft's Azure Landing Zone, the reference architecture for organizing subscriptions at enterprise scale.
Each subscription can belong to only one Management Group at a time, but can be moved between Management Groups.
3.7 Subscription Transferβ
A subscription can be transferred to another Tenant or another billing account. This is an administrative process distinct from technical resource management:
Billing transfer: changes who pays the invoice. Resources and role assignments are preserved if the Tenant doesn't change.
Tenant transfer (Change Directory): changes which Azure AD the subscription trusts. All role assignments are lost. Managed Identities are reset. Application Service Principals need to be recreated in the new Tenant.
4. Structural Viewβ
How Subscriptions interact with other governance conceptsβ
The Subscription is the convergence point of all governance concepts studied in previous modules: it's the scope where RBAC, Policy, Locks, and Tags can be applied to cover all RGs and resources within.
5. Practical Operationβ
Subscription Lifecycleβ
Important non-obvious behaviorsβ
The subscription has its own Activity Log. Every resource creation, modification, and deletion event in a subscription is recorded in the subscription's Activity Log. This log is retained for 90 days by default. For longer retention, configure export to Log Analytics or Storage Account.
Moving subscription between Management Groups doesn't affect resources. When you move a subscription from one Management Group to another, policies and role assignments from the source MG stop applying and those from the new MG start taking effect. The resources themselves are not affected, but governance changes immediately.
Subscriptions don't communicate with each other by default. Resources in different subscriptions have no automatic network connectivity. To connect networks between subscriptions, VNet Peering cross-subscription or VPN Gateway is required.
Quota limits are per subscription per region. The vCPU limit is not global: it's separate by VM family (D-series, E-series, etc.) and by region. You can have 100 D-series vCPUs in East US but only 10 in Brazil South. Capacity planning requires checking quotas in the specific region where resources will be created.
Subscription billing has delay. Cost data in Cost Management has up to 72-hour delay for some services. Don't make scaling decisions based on real-time numbers without considering this delay.
6. Implementation Methodsβ
Azure Portalβ
To view and manage subscriptions:
- Portal > Subscriptions (search in search bar or menu)
- List of all subscriptions you have access to
- Click on a subscription to see: overview, IAM, policies, cost, resources
To check and request quota increases:
- Portal > Subscriptions > select subscription
- Usage + quotas in sidebar menu
- Filter by provider, region, and resource type
- Click Request increase for types with insufficient limit
To move subscription between Management Groups:
- Portal > Management Groups
- Locate the subscription
- Select Move and choose destination Management Group
Portal limitation: creating subscriptions via portal is limited depending on enrollment type. EA and MCA have specific processes.
Azure CLIβ
# List all accessible subscriptions
az account list --output table
# View active subscription in current context
az account show
# Change active subscription in CLI context
az account set --subscription "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
# or by name:
az account set --subscription "Company-Prod"
# View complete details of a subscription
az account show --subscription "<sub-id>" --output json
# List all available locations in a subscription
az account list-locations --output table
# Check vCPU quotas in a region
az vm list-usage \
--location "brazilsouth" \
--output table
# Check quota for a specific resource
az vm list-usage \
--location "brazilsouth" \
--query "[?name.value=='cores']" \
--output table
# List registered resource providers in subscription
az provider list \
--query "[?registrationState=='Registered'].namespace" \
--output tsv
# Register a resource provider
az provider register --namespace "Microsoft.Compute"
# Check registration status
az provider show --namespace "Microsoft.Compute" --query "registrationState"
# Move subscription to different Management Group
az management-groups subscription add \
--name "mg-landing-zones" \
--subscription "<sub-id>"
# List subscriptions in a Management Group
az management-groups entities list \
--name "mg-landing-zones" \
--query "[?type=='Microsoft.Management/managementGroups/subscriptions'].{Name:displayName, ID:name}" \
--output table
# Create cost alert on a subscription
az consumption budget create \
--budget-name "budget-sub-prod-monthly" \
--amount 10000 \
--time-grain Monthly \
--start-date "2026-04-01" \
--end-date "2027-03-31" \
--notifications '{
"actual_GreaterThan_80_Percent": {
"enabled": true,
"operator": "GreaterThan",
"threshold": 80,
"contactEmails": ["cloud-team@company.com", "finance@company.com"]
},
"actual_GreaterThan_100_Percent": {
"enabled": true,
"operator": "GreaterThan",
"threshold": 100,
"contactEmails": ["cto@company.com"]
}
}'
# View current subscription cost
az consumption usage list \
--start-date "2026-03-01" \
--end-date "2026-03-24" \
--output table
# Check subscription activity log (latest operations)
az monitor activity-log list \
--max-events 20 \
--output table
Azure PowerShellβ
# List accessible subscriptions
Get-AzSubscription | Select-Object Name, Id, State, TenantId
# Change context to a subscription
Set-AzContext -SubscriptionId "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
# Or by name
Set-AzContext -Subscription "Company-Prod"
# View current context
Get-AzContext | Select-Object Name, Subscription, Tenant
# Check VM usage and quotas in a region
Get-AzVMUsage -Location "brazilsouth" |
Select-Object @{N="Name"; E={$_.Name.LocalizedValue}}, CurrentValue, Limit |
Sort-Object -Property CurrentValue -Descending
# Check quotas near limit (above 80%)
Get-AzVMUsage -Location "brazilsouth" |
Where-Object { $_.Limit -gt 0 -and ($_.CurrentValue / $_.Limit) -gt 0.8 } |
Select-Object @{N="Resource"; E={$_.Name.LocalizedValue}}, CurrentValue, Limit
# Register resource provider
Register-AzResourceProvider -ProviderNamespace "Microsoft.ContainerService"
# List all resource providers and their state
Get-AzResourceProvider -ListAvailable |
Select-Object ProviderNamespace, RegistrationState |
Sort-Object RegistrationState
# Move subscription between Management Groups
New-AzManagementGroupSubscription `
-GroupId "mg-landing-zones" `
-SubscriptionId "<sub-id>"
# Create subscription budget
New-AzConsumptionBudget `
-Name "budget-sub-prod-monthly" `
-Amount 10000 `
-Category Cost `
-TimeGrain Monthly `
-StartDate "2026-04-01" `
-EndDate "2027-03-31"
Creating Subscriptions via API (EA/MCA)β
For organizations with Enterprise Agreement or Microsoft Customer Agreement, subscriptions can be created programmatically:
# Create subscription programmatically (requires appropriate billing scope)
az rest \
--method POST \
--url "https://management.azure.com/providers/Microsoft.Subscription/aliases/<alias-name>?api-version=2021-10-01" \
--body '{
"properties": {
"displayName": "Company-App-Prod",
"workload": "Production",
"billingScope": "/providers/Microsoft.Billing/billingAccounts/<accountId>/enrollmentAccounts/<enrollmentAccountId>"
}
}'
When to use API creation: automation of subscription vending machines, where new subscriptions are created automatically as part of a project or team onboarding process.
7. Control and Securityβ
Subscription Access Modelβ
Access to a subscription follows exactly the RBAC model studied in previous modules, but with specific implications:
Who should be the Subscription Owner? Subscription Owner is a very powerful role and should be restricted. Best practices recommend:
- Maximum of 2 to 3 people with Owner (for operational continuity)
- Use Azure AD groups instead of individual users
- Use Privileged Identity Management (PIM) for just-in-time Owner access
Resource Providers: what they are and why they matterβ
Before creating any resource in a subscription, the corresponding Resource Provider needs to be registered. A Resource Provider is the ARM service responsible for managing that type of resource.
For example:
Microsoft.Computefor VMs and disksMicrosoft.Networkfor VNets, NSGs, Load BalancersMicrosoft.Storagefor Storage AccountsMicrosoft.KeyVaultfor Key VaultsMicrosoft.ContainerServicefor AKS
Many providers are automatically registered when you create the first resource of that type. But in automation via scripts, it may be necessary to register explicitly before creating resources.
# Check if a provider is registered
az provider show --namespace "Microsoft.ContainerService" \
--query "registrationState" --output tsv
# Register if not already registered
az provider register --namespace "Microsoft.ContainerService"
# Wait for registration to complete
az provider show --namespace "Microsoft.ContainerService" \
--query "registrationState" --output tsv
# Repeat until it returns "Registered"
Cost diagnosis and anomaliesβ
Configure cost anomaly alerts in Cost Management to detect unexpected spending:
8. Decision Makingβ
How many subscriptions to useβ
| Situation | Recommendation | Reason |
|---|---|---|
| Startup or small project | 1 subscription | Operational simplicity, low management cost |
| Company with prod and dev | Minimum 2 subscriptions (prod, dev) | Risk isolation, separate billing |
| Enterprise with multiple applications | 1 sub per application per environment | Complete isolation, precise chargebacks, independent quotas |
| Quota limit reached | New subscription | Quotas are per subscription; new sub = new quotas |
| Compliance requires complete isolation | Dedicated subscription | No resource from other context in same perimeter |
| Team with complete autonomy | Own subscription | Teams can manage without impacting others |
When to create new Subscription vs. new Resource Groupβ
| Need | Choice | Reason |
|---|---|---|
| Separate dev from prod logically | Separate subscription | Independent billing, independent quotas, real isolation |
| Separate two projects with same environment | Separate Resource Group | Same environment, billing in same sub, simpler |
| Reached quota limit in a sub | New subscription | Quotas are per subscription, not per RG |
| Compliance requiring complete network isolation | Separate subscription | VNets in different subs are isolated by default |
| Team needs autonomy without affecting others | Separate subscription | Independent RBAC and Policy |
| Just visual/organizational separation | Separate Resource Group | Overhead of managing sub doesn't justify |
Subscription type choiceβ
| Situation | Recommended type | Reason |
|---|---|---|
| Company with predictable and high spending | Enterprise Agreement | Volume discounts, centralized billing |
| Medium-sized company | Microsoft Customer Agreement | Similar flexibility to EA, without such high minimum commitment |
| Team dev/test | Visual Studio Dev/Test | Reduced prices for non-production environments |
| Experimentation without commitment | Pay-As-You-Go | No contract, pay only what you use |
| New project that needs testing | Free Trial or Sandbox | Initial credits at no cost |
9. Best Practicesβ
Define a subscription model before starting to create resources. Subscription organization is hard to refactor later. Deciding the model (by environment, by application, by team) before provisioning the first resources saves enormous work in the future.
Use Management Groups for governance at scale. With more than 2 subscriptions, Management Groups are essential. Policies and RBAC applied at the Management Group propagate to all subscriptions below, eliminating the need to repeat configurations.
Deploy the Azure Landing Zone pattern for organizations. Microsoft provides the Azure Landing Zone as code (Terraform/Bicep) that creates the Management Groups hierarchy, platform subscriptions (network, identity) and application subscriptions with all baseline governance configured. It's the recommended starting point for any organization that will use Azure at scale.
Monitor quotas proactively. Configure alerts when vCPU usage reaches 70% of the limit. Requesting quota increases takes hours to days, and waiting until reaching 100% causes unavailability in deployments.
Keep the number of Owners minimal and use PIM. Subscription Owner is extremely powerful. With Privileged Identity Management, owners receive the role only when needed, for limited time, with approval and auditing.
Separate production subscriptions from development. Never put production and development resources in the same subscription. The risk of cross-impact (shared quotas, mixed billing, accidental deletion risk) doesn't justify the simplification.
Configure budgets and cost alerts on every new subscription. Every subscription created should immediately have a budget configured with alerts at 80% and 100%. Discovering excessive spending only on the month's bill is too late.
Use consistent naming convention for subscriptions.
Names like company-production, company-development, company-sandbox immediately communicate the purpose. Subscriptions with names like "Azure subscription 1" or "Test" cause operational confusion.
10. Common Errorsβ
| Error | Why it happens | How to avoid |
|---|---|---|
| Put prod and dev in same subscription | Initial simplicity, no long-term vision | Separate from the beginning; recreating later is costly |
| Not monitor quotas until hitting them | Lack of proactive visibility | Quota alerts at 70% to request increase before need |
| Give Owner to too many people | Access convenience, lack of process | Maximum 2-3 owners, PIM for elevated access |
| Transfer subscription from Tenant without planning RBAC | Not knowing that role assignments are lost | Document all access before transfer, reconfigure in new Tenant |
| Not register resource providers in automation | Script works in portal (automatic registration) but fails in pipeline | Include provider registration step in pipelines |
| Confuse Tenant with Subscription | Similar terminology, distinct concepts | Tenant = identity (AD); Subscription = billing and resources |
| Create subscriptions without Management Group | Individual governance per subscription doesn't scale | Define MG hierarchy before creating subscriptions |
| Not configure budget when creating subscription | Cost isn't a priority initially | Include budget creation as mandatory part of subscription creation process |
| Use subscription name in scripts instead of ID | Name can change; ID is permanent | Always reference subscription by ID in scripts |
The most costly errorβ
Creating all resources from all projects in a single subscription without environment separation. When the vCPU quota is reached by a processing job in development, production deployments fail. When a developer accidentally deletes a Resource Group with the wrong name, they take production resources along. Separation into subscriptions is fundamental protection, not bureaucracy.
11. Operation and Maintenanceβ
Subscription audit and inventoryβ
# List all subscriptions with state and Tenant
az account list \
--query "[].{Name:name, ID:id, State:state, Tenant:tenantId}" \
--output table
# Check subscription with most resources (for migration planning)
az graph query -q "
Resources
| summarize count() by subscriptionId
| order by count_ desc" \
--subscriptions "<sub-id1>" "<sub-id2>"
# List all owners of a subscription
az role assignment list \
--role "Owner" \
--scope "/subscriptions/<sub-id>" \
--include-inherited \
--output table
# See critical quotas in all regions
for region in brazilsouth eastus westeurope; do
echo "=== $region ==="
az vm list-usage \
--location "$region" \
--query "[?currentValue > 0].{Resource:name.localizedValue, Current:currentValue, Limit:limit}" \
--output table
done
Cost monitoring and anomaliesβ
# See total subscription cost in current month
az consumption usage list \
--start-date "$(date -d 'first day of this month' +%Y-%m-%d)" \
--end-date "$(date +%Y-%m-%d)" \
--query "sum([].pretaxCost)" \
--output tsv
# See the 10 most expensive resources of the month
az consumption usage list \
--start-date "2026-03-01" \
--end-date "2026-03-24" \
--query "sort_by([].{Resource:instanceName, Cost:pretaxCost, Currency:currency}, &Cost) | reverse(@) | [:10]" \
--output table
# Check all configured budgets
az consumption budget list --output table
Configure Activity Log export for long-term retentionβ
By default, the subscription Activity Log retains only 90 days. For long-term compliance and auditing:
# Create diagnostic setting to export Activity Log to Log Analytics
az monitor diagnostic-settings create \
--name "sub-activity-log-export" \
--resource "/subscriptions/<sub-id>" \
--workspace "<log-analytics-workspace-id>" \
--logs '[
{"category": "Administrative", "enabled": true},
{"category": "Security", "enabled": true},
{"category": "ServiceHealth", "enabled": true},
{"category": "Alert", "enabled": true},
{"category": "Policy", "enabled": true}
]'
Important Subscription limits for daily operationsβ
| Limit | Value | Operational impact |
|---|---|---|
| Resource Groups per subscription | 980 | Rarely reached; indicates need for new subscription if close |
| Role assignments per subscription | 4,000 | Important to monitor in large orgs; use groups |
| Standard vCPUs per region | 20 (PAYG) / higher in EA | Request increase before needing |
| Public IP per subscription | 20 | Request increase for environments with many exposed services |
| Storage Accounts per region | 250 | Relevant for architectures with many storage accounts |
| Deployments in Activity Log | No creation limit, but UI shows up to 800 per RG | Export to Log Analytics for complete history |
12. Integration and Automationβ
Subscription Vending Machineβ
In enterprise organizations, the process of creating new subscriptions is automated as a "vending machine": a developer or team requests a new subscription via form or pipeline, and the process automatically creates the subscription, places it in the correct Management Group, configures baseline RBAC, applies tags, and creates budgets.
Terraform for subscription management at scaleβ
# Create subscription (requires billing scope from EA or MCA)
resource "azurerm_subscription" "app_prod" {
subscription_name = "company-app-production"
billing_scope_id = "/providers/Microsoft.Billing/billingAccounts/<account>/enrollmentAccounts/<enrollment>"
workload = "Production"
tags = {
Environment = "Production"
Project = "app"
Owner = "cloud-team"
CreatedBy = "terraform"
}
}
# Move to Management Group
resource "azurerm_management_group_subscription_association" "app_prod" {
management_group_id = "/providers/Microsoft.Management/managementGroups/mg-corp-prod"
subscription_id = azurerm_subscription.app_prod.id
}
# Create budget in subscription
resource "azurerm_consumption_budget_subscription" "app_prod_budget" {
name = "budget-app-prod-monthly"
subscription_id = azurerm_subscription.app_prod.id
amount = 15000
time_grain = "Monthly"
time_period {
start_date = "2026-04-01T00:00:00Z"
end_date = "2027-03-31T00:00:00Z"
}
notification {
enabled = true
threshold = 80
operator = "GreaterThan"
threshold_type = "Actual"
contact_emails = ["cloud-team@company.com"]
}
notification {
enabled = true
threshold = 100
operator = "GreaterThan"
threshold_type = "Actual"
contact_emails = ["cto@company.com", "finance@company.com"]
}
}
Integration with Microsoft Cost Management APIsβ
For automated cost reports by subscription:
# Export subscription cost report to Storage Account (automatic monthly)
az consumption export create \
--name "export-monthly-sub-prod" \
--type ActualCost \
--billing-period-start "2026-04-01" \
--billing-period-end "2027-03-31" \
--recurrence Monthly \
--recurrence-period from="2026-04-01" to="2027-03-31" \
--storage-account-id "/subscriptions/<sub-id>/resourceGroups/rg-billing/providers/Microsoft.Storage/storageAccounts/stgbillingexport" \
--storage-container "cost-exports" \
--storage-directory "sub-production"
13. Final Summaryβ
Essential points:
- A Subscription is the billing unit and the fundamental administrative perimeter of Azure
- Every subscription is associated with exactly one Azure AD Tenant, which provides authentication
- Subscriptions contain Resource Groups, which contain resources; the hierarchy is Tenant > Management Group > Subscription > Resource Group > Resource
- Service Limits (Quotas) are defined per subscription and per region, independent between subscriptions
- Subscriptions can become Disabled due to lack of payment, with a 90-day period before permanent resource deletion
- Resource Providers must be registered in a subscription before creating resources of the corresponding type
Critical differences:
- Tenant vs. Subscription: Tenant is identity (Azure AD); Subscription is billing and resources. One Tenant can have many subscriptions
- Billing transfer vs. Tenant transfer: changing who pays preserves RBAC; changing the Tenant destroys all role assignments
- New Subscription vs. New Resource Group: new subscription = new quotas, separate billing, real isolation; new RG = only logical organization within the same subscription
- Management Group vs. Subscription: MG is governance container; Subscription is billing and resource unit
What needs to be remembered for AZ-104:
- The Disabled state preserves resources for 90 days before permanent deletion
- Critical limits: 980 RGs per subscription, 4,000 role assignments per subscription
- Transferring subscription to another Tenant destroys all role assignments
- Resource Providers need to be registered before creating resources of the corresponding type
- Management Groups allow applying RBAC and Policy at scale across multiple subscriptions with inheritance
- vCPU quotas are per subscription per region per VM family, not global
- In scripts and automation, always reference subscription by ID (GUID), not by name
- The subscription Activity Log retains events for 90 days by default; export to Log Analytics for longer retention