Azure Compute Cost savings

Aammir Mirza
4 min readJan 30, 2022

Start/Stop VMs and Scale-sets during off-hours (NonWorking Hours)

The Start/Stop VMs or VM Scalesets during off-hours (for development, test, lab env) feature start or stops enabled Azure VMs and VM Scaliest (VMSS).

It is nothing new or out-of-the-box idea.

We all are already practising it with Runbook (Automation account), Azure provided feature within VM scope or via pipelines. But I have experienced some issues to make it more scheduled and parameterized, so it can be used within pipelines on-demand.

For example, if my RG consists of 14 VMs but I just want to enable the STOP schedule for 12 VMs, how can I exclude the rest of 2 from the schedule?

Every time change in schedule requires you to go and change the parameters or schedules for the automation in Runbooks or Azure internal feature.

How to set the same schedule for 50+ VMs across 7 subscriptions and 15 different RGs, with a single pipeline and automation schedule.

Etc etc…

What if we have a single extension for Azure DevOps or GitHub that take care of all such small cosmetic changes to keep the Start/Stop schedule more flexible?

Extension link for Azure VM(s) Start/Stop schedule Link

Extension link for Azure VMSS (Scale set) Start/Stop Link

Introducing Azure VM Start/Stop extension

It starts or stops machines on user-defined schedules. The feature can be enabled on Azure Resource Manager VMs for most scenarios.

Microsoft best practice (recommendation) for cost saving

Optimise virtual machine spending by resizing or shutting down under-utilised instances Although certain application scenarios can result in low utilisation by design, you can often save money by scheduling the shutdown of your virtual machines.

The recommended actions are shut down or resize, specific to the evaluated resource.

The advanced evaluation model in Advisor considers shutting down virtual machines when all of these statements are true:

The current load doesn’t go above 80% utilisation for workloads that aren’t user-facing. The burden doesn’t go above 40% for user-facing workloads. Here, Advisor determines the type of workload by analysing the CPU utilisation characteristics of the workload.

Also, the extension supports the Startup of the VMs which can be scheduled as the same way as Shut down

Automate schedule with Azure DevOps pipeline using AzureVMStart/Stop task. It can reduce the overhead of maintaining / modifying individual Virtual Machine schedules every now and then from Portal or AzCLI. By scheduling the AzDO pipeline with this extension we can Shutdown / Startup computes based on requirement.

The extension also provides flexibility to manage VMs based on the below possible conditions:

  • Run for all VMs within the listed ResourceGroup(s), using the resource group field, with exclude list of VMs option (if required) for exclusion of VMs in the RG.
  • Run for all VMs listed in VM List (applicable for single RG only)
  • If no arguments (neither ResourceGroup nor VM List) is provided, it will run for all the RGs and VMs within the scope of Service Connection with exclude list of VMs option (if required)

Sample evaluation of cost-saving within a week

How much could you save shutting down Non-Production VMs ?

Pipeline and execution example

Running a Start schedule for the Azure VMs within multiple RGs, including exclusion on some VMs.

schedules:- cron: "0 18, * * *" #Run pipeline to STOP the VMs at 06PM  displayName: Daily turnoff schedule  branches:include:- mainalways: truename: $(Build.BuildId)_STOP_VMs  # build numbering formatparameters:- name: Action  displayName: Action  type: string  default: Stopvalues:- Start- Stop- Restarttrigger:- mainpool:vmImage: windows-lateststeps:- task: AzureVMStartStop@1  inputs:   ResourceGroupName: $(ResourceGroupName)   Action: 'Stop'   ConnectedServiceName: 'sc-cbsed-lab'   Simulate: false   vmsExcludedFromAction: '$(vmsExcludedFromAction)'  displayName: 'VM - Stop Schedule'

Variables for pipeline

ResourceGroupName: list of RGs, for which cost-saving across VMs is running. In my case, all the 3 RGs are from a lower environment and I don't want them running after evening 1800, so I created a single pipeline for all of them.

vmsExcludedFromAction: list of VMs for which you don't want to take any action. Which means that they will continue running.

GIF for reference

STOP VMs schedule

STAR VMs schedule



Aammir Mirza

Cloud Architect with 12 years of experience in managing cloud infrastructure and automation, integrating Azure cloud-based infra components