Stage 5 · Platform
Infrastructure as Code on Azure
Cost Optimization Patterns
Right-sizing, auto-shutdown, reservations, and budget guardrails in IaC.
Cost Optimization Overview
Cost optimization in IaC means building cost awareness into your infrastructure definitions. Instead of reviewing costs after deployment, you prevent waste at the source through policies, automation, and architectural patterns.
- Right-size at creation — Choose the smallest VM size that meets requirements
- Automate shutdown — Stop dev/test resources outside business hours
- Use reservations — Commit to 1-3 year terms for steady-state workloads
- Enforce budgets — Set spending limits and alert on thresholds
- Tag everything — Ensure every resource has cost allocation tags
- Monitor continuously — Use Cost Management to identify waste
Right-Sizing
variable "environment" {
type = string
}
# Environment-specific VM sizes
locals {
vm_sizes = {
dev = "Standard_B2ms"
staging = "Standard_D2s_v3"
prod = "Standard_D4s_v3"
}
disk_sizes = {
dev = 64
staging = 128
prod = 256
}
}
resource "azurerm_linux_virtual_machine" "app" {
name = "vm-app-${var.environment}"
size = local.vm_sizes[var.environment]
admin_username = "azureuser"
resource_group_name = azurerm_resource_group.main.name
location = azurerm_resource_group.main.location
os_disk {
caching = "ReadWrite"
storage_account_type = var.environment == "prod" ? "Premium_LRS" : "Standard_LRS"
disk_size_gb = local.disk_sizes[var.environment]
}
}Right-sizing reduces costs by 50-70%. Start small and scale up based on actual usage. Azure Advisor provides personalized right-sizing recommendations.
Auto-Shutdown
resource "azurerm_dev_test_global_vm_shutdown_schedule" "dev_vm" {
count = var.environment == "dev" ? 1 : 0
virtual_machine_id = azurerm_linux_virtual_machine.app[0].id
location = azurerm_resource_group.main.location
enabled = true
daily_recurrence {
time = "1900" # 7 PM UTC
}
notification_settings {
enabled = true
email = "team@contoso.com"
time_in_minutes = 30
}
}
# Bicep version
resource devTestSchedule 'Microsoft.DevTestLab/schedules@2018-09-15' = {
name: 'shutdown-compute-vms'
location: location
properties: {
status: 'Enabled'
taskType: 'LabVmsShutdownTask'
dailyRecurrence: { time: '1900' }
targetResourceId: vm.id
notificationSettings: {
status: 'Enabled'
emailRecipient: 'team@contoso.com'
timeBeforeCleanupInMinutes: 30
}
}
}Auto-shutdown saves 65% on dev/test VM costs (14 hours of shutdown per day). It only applies to VMs, not AKS clusters or App Services.
Azure DevTest Labs provides auto-shutdown, cost controls, and claimable VMs for development. It automatically shuts down VMs and enforces maximum cost limits.
IaC Cost Guardrails
// Deny VMs larger than Standard_D4s_v3
var allowedVMSizes = ['Standard_B2ms', 'Standard_D2s_v3', 'Standard_D4s_v3']
resource policyDefinition 'Microsoft.Authorization/policyDefinitions@2023-04-01' = {
name: 'allowed-vm-sizes'
properties: {
policyType: 'Custom'
mode: 'Indexed'
rules: {
if: {
allOf: [
{ field: 'type', equals: 'Microsoft.Compute/virtualMachines' }
{ not: { field: 'Microsoft.Compute/virtualMachines/vmSize', in: allowedVMSizes } }
]
}
then: { effect: 'deny' }
}
}
}
// Enforce auto-shutdown on dev VMs
resource autoShutdownPolicy 'Microsoft.Authorization/policyDefinitions@2023-04-01' = {
name: 'enforce-auto-shutdown'
properties: {
policyType: 'Custom'
mode: 'Indexed'
rules: {
if: {
allOf: [
{ field: 'type', equals: 'Microsoft.Compute/virtualMachines' }
{ field: 'tags[Environment]', equals: 'dev' }
]
}
then: {
effect: 'deployIfNotExists'
details: {
type: 'Microsoft.DevTestLab/schedules@2018-09-15'
existenceCondition: {
field: 'Microsoft.DevTestLab/schedules/taskType'
equals: 'LabVmsShutdownTask'
}
}
}
}
}
}Cost guardrails prevent expensive resources from being deployed. Start with Audit, then switch to Deny once the team is aligned.
Reservations in IaC
# Reserved VM instances for production
resource "azurerm_reserved_vm_instance" "prod" {
resource_group_name = azurerm_resource_group.main.name
location = "eastus"
name = "prod-d4s-v3"
reservation_name = azurerm_reservation_group.prod.name
applied_scope_type = "Shared"
count = var.environment == "prod" ? 3 : 0
}
# Reservation group for the subscription
resource "azurerm_reservation_group" "prod" {
name = "rg-prod-reservations"
resource_group_name = azurerm_resource_group.main.name
location = "eastus"
reservation_order_id = var.reservation_order_id
}Reservations are purchased through the Azure Portal or CLI, not Terraform. Define the expected reservation usage in Terraform for documentation and planning.
Cost Monitoring Automation
#!/usr/bin/env bash
set -euo pipefail
SUBSCRIPTION="{subscription-id}"
BUDGET_AMOUNT=10000
# Check current month spending
CURRENT_COST=$(az cost management query \
--type Usage \
--time-period from=$(date -d "first day of this month" +%Y-%m-%d) \
to=$(date +%Y-%m-%d) \
--query "properties.totalCost" --output tsv)
# Calculate percentage
PERCENTAGE=$(echo "$CURRENT_COST / $BUDGET_AMOUNT * 100" | bc -l | cut -d. -f1)
if [ "$PERCENTAGE" -gt 80 ]; then
echo "WARNING: Cost is ${PERCENTAGE}% of budget ($$CURRENT_COST / $$BUDGET_AMOUNT)"
# Send alert via Teams webhook
curl -X POST "$TEAMS_WEBHOOK" \
-H "Content-Type: application/json" \
-d "{\"text\":\"Azure costs are at ${PERCENTAGE}% of budget\"}"
fiAutomate cost monitoring with scheduled scripts or Azure Functions. Alert at 80% (warning) and 90% (critical) of budget thresholds.
Set up monthly cost reviews, quarterly right-sizing audits, and annual reservation planning. Cost optimization requires continuous attention as workloads evolve.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.