Azure Cost Management, Monitoring & Scaling: Optimize Performance & Budget
Track spend, set alerts, and scale resources dynamically—ensuring performance while avoiding waste in Azure environments.
Overview
In modern cloud deployments, cost efficiency is as critical as performance and reliability. Azure provides comprehensive tools to monitor usage, forecast spending, set budget alerts, and dynamically scale resources to match demand—without compromising availability or user experience.
This lesson consolidates knowledge from prior modules—including security, DevOps, and service architecture—to implement a cost-optimized monitoring and scaling strategy. You'll learn how to proactively manage cloud expenditure, correlate performance metrics with operational changes, and automate scaling decisions using Azure-native services like Azure Cost Management, Azure Monitor, and Azure Automation.
By the end, you'll be able to:
- Set up budget alerts and track consumption across scopes (subscription, resource group, resource)
- Correlate usage, performance, and cost data using Azure Monitor and Log Analytics
- Configure automatic scaling rules for compute, storage, and database resources
- Apply FinOps best practices to reduce waste and improve ROI
Core Concepts
Azure Cost Management + Billing
Azure Cost Management is a suite of tools integrated with Azure Billing that enables real-time tracking, forecasting, and optimization of cloud spending. It operates at multiple scopes:
- Subscription level: View costs for a single subscription
- Resource Group level: Track spending for a logical grouping of resources (e.g.,
rg-webapp-prod) - Management Group level: Aggregate costs across multiple subscriptions (e.g., dev/test vs. prod)
- Resource level: Monitor cost per individual resource (e.g., a specific
Microsoft.Web/sites)
Cost data is collected hourly and updated in near real time. You can also export cost data to CSV, Excel, or a Power BI dataset for deeper analysis.
Azure Monitor & Log Analytics
Azure Monitor is the centralized platform for collecting, analyzing, and acting on telemetry data. It includes:
- Metrics: Time-series data (e.g., CPU %, Requests/sec, Bytes sent)
- Logs: Structured JSON data from Diagnostic Settings (e.g., VM insights, Application Insights, Activity Log)
- Activity Log: Subscription-level events (e.g., VM create/delete, RBAC changes)
Log Analytics workspaces store and query log data using Kusto Query Language (KQL). You can build alerts on metrics or logs to trigger automated actions (e.g., scale out on high CPU).
resources in KQL to correlate data across multiple resources. For example:
union * | where TimeGenerated > ago(1h) | summarize count() by bin(TimeGenerated, 5m), _ResourceId
Automatic Scaling (Scale Sets & Autoscale)
Azure offers three primary scaling mechanisms:
- Virtual Machine Scale Sets (VMSS): Deploy and manage groups of identical VMs with autoscale rules
- Azure App Service Autoscale: Scale web apps based on CPU, memory, or queue length
- Azure Kubernetes Service (AKS) HPA/VPA: Horizontal Pod Autoscaler (HPA) and Vertical Pod Autoscaler (VPA)
Autoscale policies can be time-based (e.g., scale up 8 AM–6 PM weekdays) or metric-based (e.g., scale out when average CPU > 75% over 5 minutes).
FinOps Practices
FinOps (Cloud Financial Management) is a cultural and operational framework for cloud cost optimization. Key practices include:
- Tagging strategy: Enforce consistent tags (
Environment,Owner,CostCenter) at provisioning time - Reservations & Savings Plans: Commit to 1-year or 3-year usage for up to 72% discounts on VMs and SQL DBs
- Idle & Underutilized Resource Detection: Use Azure Cost Management + Advisor to find idle VMs, unused IPs, orphaned disks
- Right-Sizing: Adjust VM SKUs based on actual usage (e.g., downsize from Standard_D4s_v3 to Standard_D2s_v3)
How It Works: End-to-End Flow
Step 1: Set Up Budgets & Alerts
Start by defining a monthly budget for a resource group (e.g., rg-fin-prod) and configuring alerts to notify stakeholders when spending exceeds thresholds.
Azure Portal Steps:
- Navigate to Cost Management + Billing → Cost Management + Analysis
- Click Budgets → + Add
- Select scope:
SubscriptionorResource Group - Set Budget amount (e.g.,
1000USD) - Define alert thresholds (e.g.,
50%,75%,90%) - Configure notification: Email addresses or Azure Monitor action group
CLI Equivalent:
# Login and set subscription
az account set --subscription "your-subscription-id"
# Create a budget for a resource group
az costmanagement budget create \
--name "prod-budget-q3" \
--amount 1000 \
--category "Cost" \
--time-period start-date=2024-07-01T00:00:00Z end-date=2024-09-30T00:00:00Z \
--time-grain "Monthly" \
--resource-group "rg-fin-prod" \
--notification "Email" \
--threshold 50 \
--action "notify@company.com"
Step 2: Configure Monitoring & Diagnostics
Enable diagnostics on key resources (e.g., Azure App Service, VM, SQL DB) to send logs and metrics to Azure Monitor.
Azure Portal Steps (for an App Service):
- Go to your App Service → Diagnostic settings
- Click + Add diagnostic setting
- Enable Application Logs (Filesystem) and HTTP Logs
- Send logs to a Log Analytics workspace
- Save
CLI Equivalent (enable diagnostics for a VM):
# Create a Log Analytics workspace (if not exists)
az monitor log-analytics workspace create \
--resource-group "rg-fin-prod" \
--workspace-name "law-prod-01"
# Enable VM diagnostics
az vm extension set \
--resource-group "rg-fin-prod" \
--vm-name "vm-web-01" \
--name "AzureMonitorWindowsAgent" \
--publisher "Microsoft.Azure.Diagnostics" \
--settings '{"workspaceId":"YOUR_WORKSPACE_ID"}' \
--protected-settings '{"workspaceKey":"YOUR_PRIMARY_KEY"}'
AZ-900 Exam Tip: Diagnostic Settings allow you to route logs to a Log Analytics workspace, Storage Account, or Event Hub. For long-term retention and analysis, use Log Analytics.
Step 3: Create Metric Alerts & Autoscale Rules
Use metric alerts to trigger scaling actions. Example: Scale out when CPU > 75% for 5 minutes.
Azure Portal Steps:
- Navigate to your VM Scale Set → Scale set → Autoscale
- Select profile: Default
- Click + Add rule
- Set condition: CPU Percentage > 75 over last 5 minutes (Average)
- Action: Increase instance count by 1
- Save
- Repeat for scale-in rule: CPU < 30%, Decrease by 1
CLI Equivalent (autoscale rule for a scale set):
# Get resource ID
SCALESET_ID=$(az vmss show \
--resource-group "rg-fin-prod" \
--name "vmss-web-01" \
--query "id" --output tsv)
# Create autoscale setting
az monitor autoscale create \
--resource "$SCALESET_ID" \
--name "autoscale-web" \
--min-count 2 \
--max-count 10 \
--default-count 2 \
--rule scale out 1 5 75 \
--rule scale in 1 5 30
The --rule format is: scale [direction] [count] [time-window] [metric] [threshold]
Step 4: Analyze Cost & Performance in Azure Portal
Use the Cost Analysis and Usage + Cost dashboards to identify high-cost resources and trends over time.
- Filter by
Resource Type(e.g.,Microsoft.Compute/virtualMachines) - Group by
Subscription,Resource Group, orTag - Compare current month vs. prior month
Screenshot Description: The Cost Analysis chart shows a spike in cost on Day 12—correlating with a new AKS cluster deployment. Drill-down reveals Standard_D4s_v3 VMs in rg-aks-prod account for 68% of spend.
Use KQL to investigate:
Usage
| where TimeGenerated > ago(7d)
| where ResourceProvider == "Microsoft.Compute"
| summarize TotalCost = sum(CostInCurrency) by bin(TimeGenerated, 1d), ResourceId
| render timechart
Combine with Resource Metrics to validate if the cost spike correlates with increased CPU/memory usage.
Hands-On Lab: Build a Cost-Optimized Web App with Auto-Scaling
Scenario: You've deployed a web app in Azure App Service. Traffic is unpredictable, and you need to ensure high availability during peak hours while minimizing cost during off-peak times.
Goal: Deploy a web app, enable monitoring, configure autoscale, and set up a cost budget alert.
Phase 1: Provision Resources
# Create resource group
az group create --name "rg-lab-cost" --location "eastus"
# Create App Service plan (S2 SKU = Standard, 2 cores)
az appservice plan create \
--name "asp-lab-cost" \
--resource-group "rg-lab-cost" \
--sku S2 \
--number-of-workers 2
# Create web app
az webapp create \
--name "webapp-lab-cost-2024" \
--resource-group "rg-lab-cost" \
--plan "asp-lab-cost"
Phase 2: Enable Diagnostics & Deploy Test Traffic
# Enable Application Logging
az webapp logging config \
--resource-group "rg-lab-cost" \
--name "webapp-lab-cost-2024" \
--application-logging filesystem \
--level Verbose
# Create Log Analytics workspace
az monitor log-analytics workspace create \
--resource-group "rg-lab-cost" \
--workspace-name "law-lab-01"
# Connect workspace to web app (via Diagnostic Settings)
az monitor diagnostic-settings create \
--name "diag-webapp" \
--resource "/subscriptions/YOUR_SUB_ID/resourceGroups/rg-lab-cost/providers/Microsoft.Web/sites/webapp-lab-cost-2024" \
--workspace "law-lab-01" \
--logs '[
{
"category": "AppServiceAppLogs",
"enabled": true
}
]'
Simulate traffic:
# Deploy sample app (PHP)
az webapp deployment source config-zip \
--resource-group "rg-lab-cost" \
--name "webapp-lab-cost-2024" \
--src "https://github.com/Azure-Samples/php-docs-hello-world/archive/master.zip"
# Generate load (100 requests over 60 seconds)
for i in {1..100}; do
curl -s -o /dev/null "https://webapp-lab-cost-2024.azurewebsites.net/"
sleep 0.6
done
Phase 3: Configure Autoscale for App Service
App Service autoscale uses instance-based scaling (not VM scale sets). You configure it via the Scale Out (App Service Plan) tab.
# Get App Service Plan ID
PLAN_ID=$(az appservice plan show \
--name "asp-lab-cost" \
--resource-group "rg-lab-cost" \
--query "id" --output tsv)
# Configure autoscale via CLI (preview feature—requires --preview flag in newer CLI)
az monitor autoscale setting create \
--name "autoscale-webapp" \
--resource "$PLAN_ID" \
--setting "autoscale-webapp" \
--min-capacity 2 \
--max-capacity 5 \
--default-capacity 2 \
--rule "scale out 1 5 70" \
--rule "scale in 1 10 30"
Important: App Service autoscale requires at least 2 instances in the plan. You cannot scale below 1 in production plans unless using Consumption (Functions).
Phase 4: Set Up Cost Budget & Alert
# Create a monthly budget of $200
az costmanagement budget create \
--name "lab-budget" \
--amount 200 \
--category "Cost" \
--time-period start-date=2024-07-01T00:00:00Z end-date=2024-07-31T00:00:00Z \
--time-grain "Monthly" \
--resource-group "rg-lab-cost" \
--notification "Email" \
--threshold 80 \
--action "cloudadmin@contoso.com"
Phase 5: Validate & Troubleshoot
Verify scaling:
# Check instance count before and after load
az webapp show \
--resource-group "rg-lab-cost" \
--name "webapp-lab-cost-2024" \
--query "possibleConflicts[0].properties.hostNames[0]" --output tsv
# Query logs in Log Analytics
az monitor log-analytics query \
--workspace "law-lab-01" \
--query "AppServiceAppLogs_CL | summarize count() by bin(TimeGenerated, 5m)"
Troubleshooting:
- If autoscale doesn't trigger, check metric thresholds—ensure CPU is the right metric for App Service (use
HttpQueueLengthorRequestsinstead for web apps) - If alerts don't fire, confirm the email address is in the same tenant and check spam folders
- Cost alerts may lag by 6–12 hours—always use forecasted cost for real-time visibility
Best Practices & Optimization Checklist
Tagging Strategy: Enforce tags at creation time with Azure Policy:
# Assign policy to require tags
az policy assignment create \
--name "require-cost-center-tag" \
--policy "/providers/Microsoft.Authorization/policyDefinitions/1a5b65db-1715-4f6b-9a4c-2a8c9f3d2b8f" \
--scope "/subscriptions/YOUR_SUB_ID" \
--params '{"tagName": {"value": "CostCenter"}}'
Reservations: Purchase reservations for predictable workloads:
# Reservation for 1 Standard_D2s_v3 VM for 1 year (eastus)
az reservation reservation create \
--catalog-item-name "Standard_D2s_v3" \
--currency USD \
--location "eastus" \
--quantity 2 \
--reserved-resource-type "VirtualMachines" \
--term "P1Y"
Right-Sizing: Use Advisor recommendations:
# Get right-sizing recommendations for VMs
az advisor recommendation list \
--resource-type "Microsoft.Compute/virtualMachines" \
--query "[?contains(category,'Cost')]" \
--output table
Use Consumption-Based SKUs: For non-critical workloads, consider:
- Azure Functions (Consumption plan)
- Azure Container Instances (ACI)
- Spot VMs for batch jobs (up to 90% savings)
Spot VMs Example:
# Create a VM with Spot priority
az vm create \
--resource-group "rg-fin-prod" \
--name "vm-batch-spot" \
--image UbuntuLTS \
--size Standard_D2s_v3 \
--priority Spot \
--max-price 0.05 \
--eviction-policy Deallocate
Summary
Azure Cost Management, Monitoring, and Scaling form a cohesive system for optimizing cloud operations. By combining proactive budgeting, real-time telemetry, and intelligent autoscaling, you can maintain performance while keeping costs under control.
Key takeaways:
- Use
Cost Management + Analysisto track spend at multiple scopes and set budget alerts - Enable
Azure MonitorandLog Analyticsto centralize telemetry and build KQL-based alerts - Apply
Autoscalerules based on realistic metrics—not just CPU—for App Services, VMSS, and AKS - Apply FinOps principles: tag resources, buy reservations, right-size, and delete unused assets
Remember: Cost optimization is not about cutting spend—it's about maximizing value per dollar.
Review Questions
1. Which Azure service aggregates cost data from multiple subscriptions?
Answer: Cost Management + Billing with Management Groups.
2. What is the minimum instance count required for App Service autoscale in a production plan?
Answer: 2 (for S1 and above). Consumption plans don't require this.
3. How can you reduce cost for a batch processing workload that can tolerate interruptions?
Answer: Use Spot VMs with --eviction-policy Deallocate and set --max-price to avoid surprise charges.
Next Steps
Previous Lesson: Azure DevOps & CI/CD: Pipelines, GitHub Actions, and Tooling Guide
Next Lesson: Azure Certification Roadmap: AZ-900 → AZ-104 → AZ-305 Explained