Azure

Performance per Pound: Premium SSD v2, Ephemeral OS Disks, and Real-World Cost Optimization

Measure at three layers to avoid false conclusions: guest IO tool, VM metrics, and disk metrics.

Performance per Pound: Premium SSD v2, Ephemeral OS Disks, and Real-World Cost Optimization. Azure article banner on grbadhon.com

Azure disk pricing punishes the default choice. Premium SSD v2 decouples capacity from IOPS and throughput, so you stop buying a larger disk purely to get faster IO, and ephemeral OS disks remove the remote OS disk bill entirely for anything you are willing to reimage. This post covers where each one fits, the documented ceilings rather than invented benchmarks, the commands to provision both, and the two template mistakes that will fail a deployment outright.

Benchmark methodology

Measure at three layers to avoid false conclusions: guest IO tool, VM metrics, and disk metrics.

  1. Linux fio
bash
# Random read write 4k mix for OLTP
sudo fio \
  --name=randrw --filename=/mnt/data/testfile \
  --rw=randrw --rwmixread=70 \
  --bs=4k --iodepth=32 --numjobs=8 \
  --ioengine=libaio --runtime=120 --time_based --group_reporting
  1. Windows DiskSpd
code
# 64k sequential read for backup or analytics
DiskSpd.exe -d120 -b64K -o32 -t8 -Sh -r -w0 C:\test\testfile.dat
  1. Collect platform metrics
  • VM: Data Disk IOPS Consumed Percentage, VM Uncached Bandwidth Consumed Percentage, Queue Depth, Latency.
  • Disk: Read Ops per second, Write Ops per second, Bytes per second.

What the platform will actually give you

This section used to carry a table of IOPS and p99 latency figures presented as a test run. They were not measured on anything, so they have been removed rather than dressed up. I have not benchmarked these disks in production, and an invented latency figure is worth less than an honest ceiling.

What the documentation does support is the budget the platform will sell you. Premium SSD v2 includes 3,000 IOPS and 125 MB/s free on every disk. Above 6 GiB the IOPS ceiling rises by 500 per GiB, so reaching the full 80,000 IOPS needs a disk of at least 160 GiB, and throughput is provisioned at 0.25 MB/s for each IOPS you set. Verified against Microsoft’s managed disk type documentation on 26 September 2026.

Those are disk ceilings, not workload results. The VM SKU imposes its own uncached IOPS and bandwidth caps, and on most sizings that cap binds before the disk does. Measure with fio or DiskSpd against your own SKU and region, and watch the VM counters alongside the disk counters, or you will tune a disk that was never the constraint.

SKU comparison and what to use when

CapabilityPremium SSD v2 (data disk)Premium SSD (OS or data)Ultra Disk
OS disk supportNoYesNo
Host cachingNoYesNo
Max IOPS per disk80,00020,000400,000
Max throughput per disk2,000 MB/s900 MB/s10,000 MB/s
Performance controlSet capacity, IOPS and throughput independentlyFixed tier by size, with optional performance tiering on some sizesSet IOPS and throughput independently
Cost modelCapacity plus provisioned IOPS plus throughputFixed by size tier, plus optional performance tier upliftCapacity plus provisioned IOPS plus throughput
Best forDatabases, queues, hot logs, game serversOS disks and general workloads on fixed tiersExtreme transactional or analytics peaks

Three numbers in that table were wrong on this page until 26 September 2026, and they were wrong in the direction that costs money. Premium SSD v2 tops out at 2,000 MB/s, not 1,200. Ultra Disk reaches 400,000 IOPS and 10,000 MB/s, not 160,000 and 2,000. If you sized against the old figures you may have reached for Ultra where v2 would have carried the workload at a lower bill, or written off v2 for a throughput target it can in fact meet.

Ephemeral OS disks

  • Store the OS on local SSD or NVMe of the VM. No remote managed OS disk. Ideal for stateless fleets that can be reimaged. AKS node pools are the obvious case, and GitOps fleet management for AKS covers the reimage workflow that makes it safe to rely on.
  • Not for long lived pets. No snapshots or backup. Plan for reimage and use configuration management.

Cost scenarios

Focus on performance per pound, not raw cheapest. The same discipline applies to compute, where what Azure actually charges for a stopped resource catches most people out at least once.

Scenario A small database that needs 8k IOPS and 250 MBps with 256 GiB of data.

  • Premium SSD v2 single disk set to 8,000 IOPS and 300 MBps.
  • Legacy Premium SSD would need a larger tier or multiple striped disks to reach 8k IOPS, which lifts capacity and cost you do not need.
  • Result fewer resources, simpler ops, lower £ per transaction.

Scenario B read heavy analytics window with daily peaks

  • Keep v2 at a low baseline, then raise IOPS and throughput for the 6 hour window using an automated az disk update in a scheduled job. A timer-triggered Function or a Logic App both do the job, and the trade-offs between the two are covered separately. You pay for the higher provisioned figures only while they are configured.
  • There is a cap on how often you can do that, and it is easy to miss: Premium SSD v2 performance can be adjusted four times in any 24 hour period, and creating the disk counts as one of them. A daily up and down cycle fits comfortably. A job that chases load hour by hour does not, and will start failing its own scale-down step. Per Microsoft’s Premium SSD v2 deployment guidance, checked 26 September 2026.

How to estimate

  • v2 monthly cost equals capacity charge plus IOPS rate times provisioned IOPS plus MBps rate times provisioned MBps. Rates vary by region. Use the workbook calculator link below to plug your figures in.
  • For Premium SSD tiers, monthly cost equals the tier price times count of disks.

IaC and commands that matter

Create Premium SSD v2 data disk and attach

Azure CLI

code
# Create disk with explicit performance
az disk create -g $RG -n data-pv2 --size-gb 256 \
  --sku PremiumV2_LRS --zone 1 \
  --disk-iops-read-write 8000 \
  --disk-mbps-read-write 300

# Attach to a VM at LUN 0, no host caching on v2
az vm disk attach -g $RG --vm-name $VM --name data-pv2 --lun 0 --caching None

# Change performance later without downtime
az disk update -g $RG -n data-pv2 \
  --disk-iops-read-write 12000 \
  --disk-mbps-read-write 500

PowerShell

powershell
$cfg = New-AzDiskConfig -Location $loc -Zone 1 -DiskSizeGB 256 `
  -AccountType PremiumV2_LRS -DiskIOPSReadWrite 8000 -DiskMBpsReadWrite 300 -CreateOption Empty
New-AzDisk -ResourceGroupName $rg -DiskName "data-pv2" -Disk $cfg
$vm = Get-AzVM -ResourceGroupName $rg -Name $vmName
$disk = Get-AzDisk -ResourceGroupName $rg -Name "data-pv2"
$vm = Add-AzVMDataDisk -VM $vm -Lun 0 -ManagedDiskId $disk.Id -CreateOption Attach -Caching None
Update-AzVM -VM $vm -ResourceGroupName $rg

Terraform

code
resource "azurerm_managed_disk" "data_pv2" {
  name                 = "data-pv2"
  location             = azurerm_resource_group.rg.location
  resource_group_name  = azurerm_resource_group.rg.name
  storage_account_type = "PremiumV2_LRS"
  disk_size_gb         = 256
  create_option        = "Empty"
  disk_iops_read_write = 8000
  disk_mbps_read_write = 300
  zone                 = 1
}

resource "azurerm_virtual_machine_data_disk_attachment" "vm_data" {
  managed_disk_id    = azurerm_managed_disk.data_pv2.id
  virtual_machine_id = azurerm_linux_virtual_machine.vm.id
  lun                = 0
  caching            = "None" # v2 does not support host caching
}

Ephemeral OS disk on a scale set

Bicep

yaml
param location string
param vmssName string
param adminUser string

resource vmss 'Microsoft.Compute/virtualMachineScaleSets@2024-03-01' = {
  name: vmssName
  location: location
  sku: {
    name: 'Standard_D2ads_v6'
    capacity: 3
    tier: 'Standard'
  }
  zones: [ '1' ]
  properties: {
    upgradePolicy: { mode: 'Rolling' }
    virtualMachineProfile: {
      storageProfile: {
        osDisk: {
          createOption: 'FromImage'
          diffDiskSettings: {
            option: 'Local'
            placement: 'NvmeDisk'
          }
        }
        dataDisks: [ ]
      }
      osProfile: {
        computerNamePrefix: 'web'
        adminUsername: adminUser
      }
      networkProfile: { }
    }
  }
}

Two details in that template will stop a deployment before it starts. The placement value is NvmeDisk, not Nvme, and the three accepted values are CacheDisk, ResourceDisk and NvmeDisk. NVMe placement also requires API version 2024-03-01 or later on the scale set resource, so an older apiVersion rejects it even when the value is spelled correctly. Both were wrong in the sample on this page until 26 September 2026. See the ephemeral OS disk documentation for the size requirements, which differ by image and by SKU.

The newsletter

Get the next Azure fix like this one by email

Subscribe and get the free 8-page Intune troubleshooting field guide (PDF), then new fixes about twice a month. From a Microsoft MVP.

Free. Confirm by email, unsubscribe in one click. Privacy.

Autoscale on disk pressure

CLI

code
# Create autoscale and rules for VMSS
az monitor autoscale create -g $RG --resource $VMSS_ID -n vmss-autoscale \
  --min-count 2 --max-count 10 --count 3

# Scale out if VM Uncached IOPS is hot
az monitor autoscale rule create -g $RG --autoscale-name vmss-autoscale \
  --condition "VM Uncached IOPS Consumed Percentage > 90 avg 10m" --scale out 1

# Scale in when cooled
az monitor autoscale rule create -g $RG --autoscale-name vmss-autoscale \
  --condition "VM Uncached IOPS Consumed Percentage < 40 avg 15m" --scale in 1

Alerting for throttling

CLI

code
# Alert when a VM is near the disk IOPS cap
az monitor metrics alert create -g $RG -n disk-iops-near-cap \
  --scopes $VM_ID \
  --condition "avg Data Disk IOPS Consumed Percentage > 90" \
  --window-size 5m --evaluation-frequency 1m \
  --description "IOPS nearing provisioned limit" --action-group $AG_ID

# Alert on bandwidth capping as well
az monitor metrics alert create -g $RG -n disk-mbps-near-cap \
  --scopes $VM_ID \
  --condition "avg VM Uncached Bandwidth Consumed Percentage > 90" \
  --window-size 5m --evaluation-frequency 1m --action-group $AG_ID

ARM metric alert

json
{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "resources": [
    {
      "type": "Microsoft.Insights/metricAlerts",
      "name": "disk-iops-near-cap",
      "apiVersion": "2018-03-01",
      "location": "global",
      "properties": {
        "severity": 2,
        "enabled": true,
        "scopes": ["/subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.Compute/virtualMachines/<vm>"] ,
        "evaluationFrequency": "PT1M",
        "windowSize": "PT5M",
        "criteria": {
          "allOf": [
            {
              "metricName": "Data Disk IOPS Consumed Percentage",
              "operator": "GreaterThan",
              "timeAggregation": "Average",
              "threshold": 90
            }
          ]
        }
      }
    }
  ]
}

Where this bites in practice

I have not run this workload in production, so there are no measured before and after numbers here and I would rather say that than invent a pair. What the pricing and metric documentation supports is the shape of the problem: a burst-sensitive API on Premium SSD v1 pays for provisioned IOPS it does not use at 3am and still throttles at lunchtime, because the disk tier is a fixed ceiling rather than a budget. Premium SSD v2 decouples capacity from IOPS and throughput, which is why the alert on Data Disk IOPS Consumed Percentage above is the metric worth wiring up first. It tells you whether you are paying for headroom or actually short of it.

FinOps checklist

  • Tag every disk with owner, environment, RPO RTO, and performance intent. Enforce it with policy at management group scope rather than asking nicely, as in the Azure landing zone governance model.
  • Right-size monthly by checking IOPS and MBps consumed versus provisioned. Trim v2 settings when peaks pass.
  • Prefer v2 for any workload with nonlinear performance needs. Keep OS on Premium SSD or Ephemeral OS disks.
  • Reserve capacity for VMs where appropriate but keep disks flexible.
  • Export metrics to Log Analytics and review weekly. Act on any chart that rides over 85 percent for more than 5 minutes.

Common questions

Premium SSD sets performance by size tier and supports OS disks and host caching, up to 20,000 IOPS and 900 MBps per disk. Premium SSD v2 lets you set capacity, IOPS and throughput independently, up to 80,000 IOPS and 1,200 MBps, but it cannot be used as an OS disk and does not support host caching.

Yes on Premium SSD v2. az disk update accepts new values for disk-iops-read-write and disk-mbps-read-write and applies them without downtime, so a read heavy analytics window can be raised for the peak and lowered afterwards from a scheduled job. You pay the higher provisioned IOPS and MBps only while they are configured.

Whenever the machine is long lived and cannot simply be reimaged. Ephemeral OS disks place the OS on the local SSD or NVMe of the VM, with no remote managed OS disk, so there are no snapshots and no backup. They suit stateless fleets managed by configuration management, not pets carrying local state.

Watch Data Disk IOPS Consumed Percentage and VM Uncached Bandwidth Consumed Percentage, plus queue depth and latency, and alert when either sits above 90 percent over a 5 minute window. Measure at three layers, a guest tool such as fio or DiskSpd, VM metrics and disk metrics, because a single layer gives false conclusions.

The monthly cost is the capacity charge plus the provisioned IOPS at the IOPS rate plus the provisioned throughput at the MBps rate, and the rates vary by region. Premium SSD is simpler, the tier price multiplied by the number of disks. That difference is why v2 often wins on cost per transaction for high IOPS workloads.

Not with Premium SSD v2. A single v2 disk can be set to the IOPS and throughput required, so a database needing 8,000 IOPS and 300 MBps at 256 GiB takes one disk. Legacy Premium SSD would need a larger tier or several striped disks, which buys capacity that is not needed and complicates operations.

The newsletter

Free: the Intune troubleshooting field guide

Subscribe and get my 8-page PDF: 13 common Intune problems, the order to check them in, and the fix for each. Then Microsoft 365 fixes from the field, about twice a month. From G.R Badhon, Microsoft MVP.

  • The field guide, sent the moment you confirm
  • New Intune, Entra ID and Purview guides as they publish
  • One field-tested fix or script per issue

Free. Confirm by email, unsubscribe in one click. Privacy.