Back to Blog
FinOps
3 min read

Stop Paying for Dev/Test VMs Overnight and Weekends

AzureCost OptimisationAutomationDevTest

Here's a simple question: Why are your dev and test VMs running at 3am on a Sunday?

Unless you have overnight batch jobs or a global team, the answer is usually "because nobody turned them off." That's expensive.

The Math

A typical dev environment might have 10 VMs costing £50/month each = £500/month.

Running 24/7: £500/month

Running business hours only (10hrs x 5 days): £500 x (50/168) = ~£150/month

Saving: £350/month = £4,200/year

And that's just one environment. Most organisations have multiple dev, test, UAT, and staging environments.

Option 1: Auto-Shutdown (Built-in)

Azure has a simple auto-shutdown feature built into every VM:

  1. Go to the VM → Auto-shutdown in the left menu
  2. Toggle to Enabled
  3. Set your shutdown time (e.g., 7:00 PM)
  4. Choose your timezone
  5. Optionally add a notification email
  6. Save

This handles the shutdown. But you still need to start them in the morning.

Option 2: Start/Stop VMs v2 (Azure Solution)

Microsoft provides a more complete solution called Start/Stop VMs v2:

  • Schedule both start and stop times
  • Apply to VMs based on tags or resource groups
  • Includes a Logic App for orchestration
  • Free (you pay for the underlying resources)

Deploy it from the Azure Marketplace: search for "Start/Stop VMs during off-hours."

Option 3: Azure Automation (Most Flexible)

For full control, use Azure Automation with PowerShell runbooks:

# Get all VMs with the "AutoShutdown" tag
$vms = Get-AzVM | Where-Object { $_.Tags.AutoShutdown -eq "true" }

foreach ($vm in $vms) {
    $status = (Get-AzVM -ResourceGroupName $vm.ResourceGroupName -Name $vm.Name -Status).Statuses[1].Code

    if ($status -eq "PowerState/running") {
        Write-Output "Stopping $($vm.Name)"
        Stop-AzVM -ResourceGroupName $vm.ResourceGroupName -Name $vm.Name -Force
    }
}

Create a similar runbook for starting VMs, then schedule both with Automation Schedules.

Option 4: Azure DevOps Pipeline

If your dev environments are created by pipelines, destroy them with pipelines:

# Scheduled pipeline to stop dev VMs
schedules:
- cron: "0 19 * * 1-5"  # 7pm Mon-Fri
  displayName: Stop Dev VMs
  branches:
    include:
    - main

steps:
- task: AzureCLI@2
  inputs:
    azureSubscription: 'your-connection'
    scriptType: 'bash'
    scriptLocation: 'inlineScript'
    inlineScript: |
      az vm deallocate --ids $(az vm list --resource-group rg-dev --query "[].id" -o tsv)

Important: Deallocate, Don't Just Shut Down

There's a difference:

  • Stop (from inside the VM): VM is off but you're still paying for compute
  • Deallocate (Stop from Azure): Compute charges stop, you only pay for storage

Always use the Azure portal, CLI, or API to stop VMs. The auto-shutdown feature does this correctly.

What About Databases?

Azure SQL and other PaaS services don't have the same on/off model. Options:

Azure SQL:

  • Use serverless tier for dev (auto-pauses after inactivity)
  • Scale down DTUs/vCores outside business hours

Cosmos DB:

  • Reduce RU/s to minimum outside business hours
  • Use autoscale with low maximum

Tagging Strategy

Use tags to control which VMs get shut down:

AutoShutdown: true
Environment: dev
ShutdownTime: 19:00
StartTime: 08:00

Your automation can then target VMs based on these tags, making it easy to add or exclude machines.

The Exceptions

Some dev/test resources should run 24/7:

  • Shared services (AD, DNS) used by multiple environments
  • Integration test environments used by offshore teams
  • Long-running build agents

Tag these as AutoShutdown: false so your automation skips them.


Want to know how much you could save by scheduling your dev environments? Our free savings snapshot analyses your non-production spend.

How mature is your cloud cost management?

Take our free 2-minute FinOps maturity test and get a personalised improvement roadmap.