Automatic modular rightsizing of Azure VM’s with special focus on Azure Virtual Desktop

It has long annoyed me that all the scaling options in Azure just add and remove hosts. They never target the host itself. Hosts are either under or overutilized in 84% of the case.

And this is especially relevant for AVD personal hostpools where users each have their own personal “VDI”.

So I’m releasing a custom PowerShell module called “ADDRS” (Azure Data Driven Right Sizing) that grabs mem/cpu performance of the VM or all VM’s in a resource group you tell it to check. It will then do some smart voodoo magic to determine what size out of an allowlist best fits.

Instructions / Example:

  • Use -WhatIf if you don’t want it to resize the VM
  • Use -Force if you want to resize a VM even if it is online (which will cause it to be shut down!)
  • Use -Boot if you want the VM to be started after resizing (by default it will stay deallocated)
  • Use -domain with your domain if your VM is domain joined
  • Use -region if your region is not westeurope
  • Use -Verbose if you want the full output incl financial projection
  • Use -Report if you want to output data to csv. Can be used together with -WhatIf
  • Modify minMemoryGB, maxMemoryGB, minvCPUs, maxvCPUs as desired for your usecase
  • You can adjust the preconfigured allowedVMTypes array to only allow specific VM types, by default it contains “Standard_D2ds_v4″,”Standard_D4ds_v4″,”Standard_D8ds_v4″,”Standard_D2ds_v5″,”Standard_D4ds_v5″,”Standard_D8ds_v5″,”Standard_E2ds_v4″,”Standard_E4ds_v4″,”Standard_E8ds_v4″,”Standard_E2ds_v5″,”Standard_E4ds_v5″,”Standard_E8ds_v5”. Overwrite it by using the following parameter:
    -allowedVMTypes @(“Standard_D4ds_v4″,”Standard_D8ds_v4”)
  • use -maintenanceWindowStartHour, -maintenanceWindowLengthInHours and –maintenanceWindowDay if you want to ignore performance data during a maintenance window (e.g. for patching) as that isn’t representative
  • Set an Azure Tag called LCRightSizeConfig with the value disabled on machines you want to ignore
  • Set an Azure Tag called LCRightSizeConfig with a machine type value (e.g. “Standard_D4ds_v4“) if you want to lock a specific size for that machine, this can be useful if you want the script to resize from current to target automatically when it runs while the VM has been deallocated.

Example -Verbose output of two VM’s being resized:


The module requires that you’ve added the % Processor Time and Available MBytes performance counters to Log Analytics:

and that your host(s) have the Azure Monitor agent installed.

The module will check if there is sufficient data about the machine in Azure Monitor, if not, no action will be taken. You can determine how far back the function looks by modifying $measurePeriodHours

If you’re using the more recent Azure Monitoring agent, add the perf counters here:

Required access

Virtual Machine Contributor to the resource group(s) containing your VM’s and Log Analytics Reader on your log analytics workspace.

Download / Installation

Option 1: Install-Module ADDRS

Option 2: get relevant functions/code from Git

and run the set-vmRightSize or set-rsgRightSize function, e.g.:

set-vmRightSize -targetVMName azvm01 -workspaceId 7ccd0949-2fd4-414e-b58c-c013cc6e445d

set-vmRightSize -targetVMName azvm01 -workspaceId 7ccd0949-2fd4-414e-b58c-c013cc6e445d -allowedVMTypes (“Standard_E8ds_v4″,”Standard_E2ds_v5″,”Standard_E4ds_v5″,”Standard_E8ds_v5”)

set-rsgRightSize -targetRSG rg-avd-we-01 -workspaceId 7ccd0949-2fd4-414e-b58c-c013cc6e445d


If you wish to run this automatically on a schedule, I recommend either using an Azure DevOps pipeline or Automation account. I’ve compiled a small guide on how to use ADDRS in an Azure Automation Account.

Right Sizing Frequency

It is recommended to match job schedules to the lookback period, or at least not run multiple times in the same lookback period. Otherwise, the data that is being used for sizing may not be representative if the machine had already been resized in an earlier run.

Issues / notes

  • Make sure you’ve got enough data in Log Analytics
  • Make sure the allowedVMTypes list contains only VM types that you can actually upgrade to. If e.g. your VM has an ephemeral disk, and your allowList has types that do not, the resize will fail with an error message (but no harm will be done to the existing VM)
  • I’ve only tested the maintenance window parameters using UTC time, if you’re using different timezones your results in excluding data generated during the maintenance window may vary from mine
  • Spot and Low Priority Azure pricing is excluded by default
Notify of

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Most Voted
Newest Oldest
Inline Feedbacks
View all comments
1 month ago

I’ve been receiving this error message when executing the code

Exception: failed to retrieve available Azure VM sizes in region canadacentral because of GenericArguments[0], ‘Microsoft.Azure.Management.Compute.Models.VirtualMachine’, on ‘T MaxInteger[T](System.Collections.Generic.IEnumerable`1[T])’ violates the constraint of type ‘T’.

Ed Penczak
Ed Penczak
7 months ago


I keep receiving the error. set-vmRightSize : <VM-Name> failed to determine optimal size because your $allowedVMTypes list does not contain any VM’s that are available in this subscription and region. Any ideas as to why this is happening?

8 months ago

What’s the recommended length of time for log ingestion before running “get-vmRightSize”?

8 months ago

For the function “get-vmCounterStats”, what is supposed to go into the “Data” field?

9 months ago

We get an error, the metrics are there. Tested the kusto query from the module and it give`s result. Any lead?

set-vmRightSize : [servername] failed to get memory performance data from Azure Monitor because Operation returned an invalid status 
code ‘NotFound’

10 months ago


I tried implementing that solution, which looks great! I have configured all VMs by Azure Monitoring Agent and I get no “Perf” Data in my Log Analytics Workspace. Its all about “InsightMetrics” where I can find the Performance Data. Can I use them aswell?


[…] For this VM rightsizing purpose, I also use a script from Jos Lieben, which helps to put your underused VM in the right size in terms of load: Automatic modular rightsizing of Azure VM’s with special focus on Azure Virtual Desktop | Liebensr… […]

Mark B
Mark B
1 year ago

Hey, great guide but i’m getting the following error? Any assistance would be wonderful.

failed to get memory performance data from Azure Monitor because no data returned by Log Analytics. 
Was the VM turned on the past hours, and has the ‘Available Mbytes’ or ‘Available Bytes’ counter been turned on, and do you have 
permissions to query Log Analytics?

Jules Waite
Jules Waite
1 year ago

Hi Jos, Thanks very much for this. Unfortunately I am struggling to get the tool to work. I have plenty of data in the LAW, resources are in same region, have all required permissions etc. But get a ‘<MyVMName> failed to get memory performance data from Azure Monitor because no data returned by Log Analytics’ error message when running the query. Very strange. This is after retrieving 666 performance rows, VM performance and pricing data cached. When running the ‘ Virtual Machine available memory’ query in the logs, it shows successful collection of data of the last 7 days. Might be… Read more »

Michał Pawlikowski
1 year ago

Hi Jos.
First of all, thanks for your tool. I’ve found it on YT video

Just one suggestion, it would be great if you would put here all the required permissions (rbac roles or specific permissions sets) to run this script. That should help setting proper security on any account that will use your tool.


Pete Conoulty
Pete Conoulty
1 year ago

This is great – would it be possible to do something similar with disk type changes HDD/SSD etc.


[…] recommended method to run my ADDRS on a schedule is through an Azure Runbook or an Azure DevOps […]