All scripts
Azure AI 573

Get-AzureVMSizeRightsizingReport

Compares average CPU utilization from Azure Monitor against VM size for every VM, flagging consistently underused machines that are likely oversized for their workload.

Get-AzureVMSizeRightsizingReport.ps1
<#
.SYNOPSIS
    Flags oversized Azure VMs based on CPU utilization history.

.DESCRIPTION
    Pulls average CPU utilization from Azure Monitor over the last N
    days for every VM and flags machines running consistently low
    utilization, a strong signal the VM size is larger than the workload
    actually needs.

.PARAMETER Days
    Number of days of metrics history to average. Defaults to 14.

.PARAMETER CpuThresholdPercent
    Average CPU percent below which a VM is flagged. Defaults to 10.

.EXAMPLE
    .\Get-AzureVMSizeRightsizingReport.ps1 -Days 30 -CpuThresholdPercent 15

.NOTES
    Requires the Az.Compute and Az.Monitor modules and an active
    Connect-AzAccount session.

.AUTHOR
    Shehryar Hassan
#>

param(
    [int]$Days = 14,
    [double]$CpuThresholdPercent = 10
)

$vms = Get-AzVM
$startTime = (Get-Date).AddDays(-$Days)

$report = foreach ($vm in $vms) {
    $metric = Get-AzMetric -ResourceId $vm.Id -MetricName "Percentage CPU" -StartTime $startTime -EndTime (Get-Date) -TimeGrain 01:00:00 -AggregationType Average
    $avgCpu = ($metric.Data.Average | Measure-Object -Average).Average
    [pscustomobject]@{
        VMName    = $vm.Name
        VMSize    = $vm.HardwareProfile.VmSize
        AvgCpuPct = [math]::Round($avgCpu, 1)
        Oversized = $avgCpu -lt $CpuThresholdPercent
    }
}

$report | Where-Object Oversized | Sort-Object AvgCpuPct | Format-Table -AutoSize

Read it before you run it, and test in a safe tenant first.