Skip to main content

Schedule Azure VM Deallocation and Morning Start

Why az vm stop keeps billing, the exact RBAC actions a scheduler needs, and how to confirm a VM is really Stopped (deallocated).

Azure has two ways to turn a VM off, and only one of them stops the compute bill. This guide sets up a nightly deallocation and a morning start with the Azure CLI, then checks the power state.

Stopped is not the same as deallocated

Microsoft’s billing table is explicit:

Power stateCompute billed?
Stopped (also shown as Stopped (Allocated) or PoweredOff), the result of az vm stop or a shutdown inside the guestYes
Deallocated, shown as Stopped (deallocated), the result of az vm deallocateNo

Even deallocated, disks and networking resources keep incurring charges. The az vm stop reference itself says the VM stays billed and points you to az vm deallocate. Any schedule you build should deallocate.

Permissions

The identity that runs the schedule needs these Azure RBAC actions on the VMs, either through a custom role or a built-in role that includes them:

  • Microsoft.Compute/virtualMachines/deallocate/action
  • Microsoft.Compute/virtualMachines/start/action
  • Microsoft.Compute/virtualMachines/read

1. Check what the VM loses

Two things do not survive deallocation:

  • Dynamic public IPs. Microsoft’s public IP documentation says a dynamic address is released when the resource is stopped. If anything allowlists the address or points DNS at it, switch the public IP to static first.
  • The temporary disk. Data on the temporary disk might be lost when you stop the VM. Anything on D: (Windows) or the resource disk (Linux) beyond page files, swap or tempdb should move to a managed data disk.

Managed OS and data disks persist and keep billing.

2. Deallocate and start from the CLI

Terminal window
# evening
az vm deallocate --resource-group rg-dev --name dev-web-01 --no-wait
# morning
az vm start --resource-group rg-dev --name dev-web-01
# every VM in a resource group
az vm deallocate --ids $(az vm list -g rg-dev --query "[].id" -o tsv)

3. Put it on a timetable

Run the two commands on a clock from something that carries an identity with the actions above: an Azure Automation runbook, a scheduled pipeline job, or a cron host with a managed identity. Whatever you use, make the evening job call deallocate, not stop.

az vm auto-shutdown exists, but it only sets a shutdown time (flags --time, --email, --webhook, --off) and has no start option, and Microsoft’s CLI reference does not say which power state it leaves the VM in. If you use it, check the state the next morning with the command below.

4. Verify the state

Terminal window
az vm get-instance-view -g rg-dev -n dev-web-01 \
--query "instanceView.statuses[?starts_with(code,'PowerState')].displayStatus" -o tsv

After the morning start you should see VM running. Overnight the status should name the deallocated state; if it only says stopped, the VM is still allocated on a host and still billing compute.

Doing it with ZopNight

ZopNight handles the deallocate versus stop distinction for Azure VMs and can put both the evening and morning actions in one schedule: cron start and stop times in an IANA timezone, attached to individual VMs or a resource group. The Azure subscription must be connected with read + write permission for scheduled execution; read-only connections get discovery and recommendations only. The resource notes are on Azure VM scheduling, and scale sets are covered on VMSS scheduling.

Stop watching the waste.
Start cutting it.

See. Find. Fix. Automatic.

Connect your first cloud account in under 5 minutes. See your first remediation in under 7. No credit card required.

CDCR connect detect classify remediate
full audit every action traceable
read-only default access
Multi-cloud automation· Production-ready in 30 min· SOC 2 · ISO 27001· 20–60% off the bill, first month· 4 platforms · 1 console· Multi-cloud automation· Production-ready in 30 min· SOC 2 · ISO 27001· 20–60% off the bill, first month· 4 platforms · 1 console·