About this article: AI-assisted writing, reviewed against the cited sources. This is source research, not a lab validation of the procedures. Check the stated versions and your own recovery requirements before making changes.
A managed disk never delivers more than the virtual machine (VM) lets through. Every Azure VM size has its own storage limits, so sustained performance is the lower of the disk limit and the VM limit. On the cached path, the host SSD has its own limit as well. Burst credits can raise a limit for a period, but they are not a ceiling of their own.
To find which limit you are hitting, read the percentage-consumed metrics at both levels. A disk at 100 per cent is capped by the disk. A VM at 100 per cent is capped by the VM, and buying faster disks will not help.
The commands come from Microsoft's published reference and from the iostat manual, and were not run in a lab for this article. The numbers are current documented limits used in hypothetical examples, not measurements.
Why it matters
Throughput problems on Azure are often answered by upgrading the disk. That spends money without changing anything if the VM size was the constraint.
There is also a timing trap. Bursting can hold a small VM or disk above its normal limit for up to 30 minutes. A benchmark or migration test that finishes inside that window can report numbers the system will not sustain in production.
Two terms are used throughout. IOPS is input/output operations per second. Throughput is the amount of data moved, in MB/s, where Azure defines 1 MB/s as 10^6 bytes per second. A workload can hit either limit first. Small random I/O tends to exhaust IOPS, and large sequential I/O tends to exhaust throughput.
How the limits stack
Microsoft describes three I/O paths on a VM:
- Uncached managed disk path, used when host caching is set to None. I/O is limited by the disk's provisioned performance and then by the VM's limit.
- Cached managed disk path, used when host caching is on. I/O passes through a local SSD on the host, which has its own limit. A cache hit is served at that level, while a miss goes on through the disk and VM limits.
- Temporary disk path, on sizes that have a temporary disk.
A disk-level cap
Microsoft's worked example uses a Standard_D8s_v3, with 12,800 uncached IOPS, and three E30 disks at 500 IOPS each. An application asks for 10,000 IOPS. The VM would allow that, but the disks answer 500 each, so the application gets 1,500.
A VM-level cap
The same VM with three P30 disks at 5,000 IOPS each has 15,000 IOPS of disk capability. An application asking for 15,000 gets 12,800, because that is the VM's uncached limit.
Nothing is wrong with any disk, and each one looks comfortably under its limit.
A worked throughput example
The cap is frequently throughput and not IOPS. This calculation is editorial, using documented limits.
A Standard_D8s_v5 has an uncached limit of 12,800 IOPS and 290 MB/s, with burst figures of 20,000 IOPS and 1,200 MB/s. Stripe two P40 disks, each 7,500 IOPS and 250 MB/s:
| Level | IOPS | MB/s |
|---|---|---|
| Two P40 disks, combined | 15,000 | 500 |
| Standard_D8s_v5 sustained, uncached | 12,800 | 290 |
| Layout’s sustained upper limits | 12,800 | 290 |
That layout pays for 500 MB/s of disk and can sustain 290 MB/s. Microsoft states the rule directly when it discusses striping: the VM size must support the combined IOPS and throughput.
Cached and uncached are separate limits
A VM's cached and uncached limits are separate, so mixing the two on one VM can reach the sum of both. Microsoft's example is the Standard_D8s_v3, with 16,000 cached and 12,800 uncached IOPS, and a total of 28,800.
Do not assume a write avoids the disk limit under caching. The accounting differs by mode:
| Operation | Read-only caching | Read/write caching |
|---|---|---|
| Read, cache hit | VM cached limit | VM cached limit |
| Read, cache miss | Cached and uncached limits | Cached and uncached limits |
| Write | Cached and uncached limits, must reach the disk | Complete on reaching host cache, written to disk later |
Read/write caching therefore acknowledges a write before the disk has it. Microsoft advises using it only if the application properly handles writing cached data to persistent disks.
Three further facts matter here. By default, cache-capable data disks have caching off and OS disks have read/write caching on. Disks of 4 TiB and larger do not support caching. Premium SSD v2 and Ultra Disk do not support host caching at all.
Bursting: two levels, two models
Disk bursting and VM bursting are separate capabilities. Either can exist without the other.
| Credit-based | On-demand | Changing the performance tier | |
|---|---|---|---|
| Applies to | Premium SSD 512 GiB and smaller, Standard SSD 1,024 GiB and smaller | Premium SSD larger than 512 GiB | All Premium SSD sizes |
| Default | On for eligible disks | Must be enabled | Manual change |
| Cost | No extra charge | Hourly enablement fee plus burst transactions | Fixed cost for each tier |
| Suits | Short peaks up to 30 minutes | Peaks without a fixed duration | Sustained demand |
The table summarises Microsoft's comparison.
How credit bursting behaves:
- A resource starts with a full bucket, enough for up to 30 minutes at the maximum burst rate.
- It earns credits while running below its target. IOPS and throughput credits are tracked separately.
- It is best effort and not guaranteed.
- A depleted bucket takes less than a day to refill.
The documented burst ceiling for Premium SSD P20 and smaller is 3,500 IOPS and 170 MB/s. For P30 and larger with on-demand bursting enabled, it is 30,000 IOPS and 1,000 MB/s.
VM-level bursting uses the credit model only and is on by default for most VMs that support Premium Storage. That default is what makes short tests misleading on a small VM. On a Standard_D8s_v5, 1,200 MB/s for a few minutes says little about the 290 MB/s that remains once credits are gone.
Choosing a disk type by its limits
| Type | Maximum IOPS | Maximum throughput | Maximum size | OS disk |
|---|---|---|---|---|
| Ultra Disk | 400,000 | 10,000 MB/s | 65,536 GiB | No |
| Premium SSD v2 | 80,000 | 2,000 MB/s | 65,536 GiB | No |
| Premium SSD | 20,000 | 900 MB/s | 32,767 GiB | Yes |
| Standard SSD | 6,000 | 750 MB/s | 32,767 GiB | Yes |
| Standard HDD | 2,000 or 3,000 | 500 MB/s | 32,767 GiB | Being retired for this use |
These are Microsoft's published maximums, and most of them apply only to the largest configurations. Standard HDD use as an OS disk is retiring on 8 September 2028.
Premium SSD performance is set by size. A 1 TiB P30 has 5,000 IOPS and 200 MB/s, so getting more performance traditionally meant buying capacity you might not need. Performance plus lifts the limits on Premium SSD, Standard SSD and Standard HDD disks of 513 GiB or larger at no extra charge, but it can be set only when a disk is created. An existing disk needs a snapshot and a new disk made from it. This article does not cover it further.
Premium SSD v2 separates the two. Every disk has a free baseline of 3,000 IOPS and 125 MB/s. Beyond 6 GiB, the maximum IOPS grows by 500 per GiB up to 80,000, and throughput can be set up to 0.25 MB/s per set IOPS. Its constraints are real:
- It cannot be an OS disk or be used with Azure Compute Gallery.
- It has no host caching.
- In most regions with availability zones, it attaches only to zonal VMs. In a subset of those regions, nonzonal disks can attach to nonzonal VMs, with extra limitations, so check which applies to your region before sizing. Australia East is listed among the regions with zonal support.
- Performance can be adjusted four times in 24 hours, and creating the disk counts as one.
Diagnosing the cap
Step 1: record the limits
Before looking at metrics, write down the numbers for the VM and for each disk. The size page gives uncached IOPS, uncached throughput and burst values. Check which disks are attached and how each is cached:
az vm show -g <rg> -n <vm> \
--query "storageProfile.dataDisks[].{lun:lun,name:name,caching:caching}" -o table
az vm show -g <rg> -n <vm> \
--query "storageProfile.osDisk.{name:name,caching:caching}" -o table
az disk show -g <rg> -n <disk> --query tier -o tsv
Step 2: read the consumed percentages
These metrics report actual use against the provisioned limit. They exist only on VM series that support premium storage.
| Metric | At 100 per cent |
|---|---|
Data Disk IOPS Consumed Percentage, Data Disk Bandwidth Consumed Percentage |
Capped by a data disk |
OS Disk IOPS Consumed Percentage, OS Disk Bandwidth Consumed Percentage |
Capped by the OS disk |
VM Uncached IOPS Consumed Percentage, VM Uncached Bandwidth Consumed Percentage |
Capped by the VM's uncached limit |
VM Cached IOPS Consumed Percentage, VM Cached Bandwidth Consumed Percentage |
Capped by the VM's cached limit |
VM_ID=$(az vm show -g <rg> -n <vm> --query id -o tsv)
az monitor metrics list --resource "$VM_ID" \
--metric "VM Uncached Bandwidth Consumed Percentage" \
--interval PT1M --aggregation Maximum
az monitor metrics list --resource "$VM_ID" \
--metric "Data Disk IOPS Consumed Percentage" \
--filter "LUN eq '*'" --interval PT1M --aggregation Maximum
Split the data disk metric by LUN, the disk's slot number. In Microsoft's walkthrough the average across data disks is about 42 per cent while two individual LUNs sit near 85 per cent. An average can hide the busy disk.
That walkthrough also explains how to read a cached disk. Data Disk IOPS Consumed Percentage counts I/O used by the disks, not what the host cache served. A low figure on that metric beside a heavy cached workload is expected. The rule does not carry over to every metric: Data Disk Read Bytes/Sec and Data Disk Read Operations/Sec include reads from the cache when caching is on.
Most of these metrics are emitted every minute. Our reasoning is that a spike much shorter than that may not stand out at this grain, so use the guest-level view in Step 4 for short events.
Step 3: check the burst credits
| Metric | Reported every |
|---|---|
VM Uncached Used Burst IO Credits Percentage, VM Uncached Used Burst BPS Credits Percentage |
5 minutes |
Data Disk Used Burst IO Credits Percentage, Data Disk Used Burst BPS Credits Percentage |
5 minutes |
Disk On-demand Burst Operations |
1 hour |
The metric descriptions define these as the accumulated percentage of burst used. If the workload slows at the moment this reaches its peak, you were depending on bursting. That inference is editorial.
Step 4: confirm inside the guest
Microsoft points to PerfMon on Windows and iostat on Linux for measuring what an application demands.
iostat -xm 5
In the iostat manual, -x shows extended statistics and -m reports in mebibytes per second. await is the average time per request in milliseconds, aqu-sz is the average queue length. On older versions the queue column may be named avgqu-sz.
Convert before you compare. Azure's MB/s is decimal and iostat -m is binary, so by our calculation a 290 MB/s cap plateaus at about 277 MiB/s in iostat. Without the conversion, a VM at its cap can look as though it has room left.
Interpreting the pattern is editorial. When a platform metric sits at 100 per cent while await and queue length climb and throughput flattens, the cap is real and measured from both sides. High latency with platform metrics well below 100 per cent points elsewhere, such as the application's I/O pattern, a guest filter driver, or one busy file on one disk.
These IOPS and throughput ceilings are not a measured guarantee or necessarily simultaneous results. The achievable combination depends on I/O size, latency, queue depth and demand.
What to choose and why
These are editorial recommendations.
| Finding | Action |
|---|---|
| Disk at 100 per cent, VM below | Raise the disk's performance: higher tier, Premium SSD v2 settings, or more striped disks |
| VM at 100 per cent, disks below | Resize the VM, or move suitable read workload to the cached path where supported |
| VM at 100 per cent only on throughput | Choose a size by its MB/s, not its vCPU count |
| Peak under 30 minutes, disk 512 GiB or smaller | Credit bursting is probably enough, but do not rely on it for a guarantee |
| Scheduled heavy period of hours or days | Change the performance tier for the period, billed at the higher tier's rate while it is set |
| Irregular peaks on a large Premium SSD | On-demand bursting, after modelling the transaction cost |
| Database needing independently tuned IOPS | Premium SSD v2, if the zonal and caching limits suit |
A performance tier lets a small disk borrow the performance of a larger one, and you pay for it. A 128 GiB P10 can be set to the P50 tier's 7,500 IOPS and 250 MB/s. While the tier is P50, the disk is billed at the P50 rate. Setting it back returns the bill to the P10 rate. The change does not require deallocating the VM:
az disk update -g <rg> -n <disk> --set tier=P50
az disk show -g <rg> -n <disk> --query tier -o tsv
Enabling on-demand bursting on an existing disk needs a Premium SSD larger than 512 GiB, and the disk detached or the VM stopped, so plan an outage:
az disk update -g <rg> -n <disk> --enable-bursting true
When testing, run longer than the burst window and start from a known credit state. Otherwise the result describes the bucket and not the system. Microsoft also advises a stripe size that suits the I/O pattern: 64 KB for SQL Server OLTP and 256 KB for a data warehouse in its examples.
Risks and limits
Warning: changing a disk's host cache setting detaches and reattaches the disk, and restarts the VM if it is the OS disk. Microsoft warns that failing to stop affected applications and services first could lead to data corruption. Treat it as a planned outage.
Warning: if you use Terraform to change a performance tier on a running VM, Terraform shuts the VM down and tries to restart it. Other methods avoid this.
- A disk tier can be downgraded only once every 12 hours, and never below the disk's baseline tier.
- Tiers apply only to Premium SSD. Shared disks need all attached VMs stopped first.
- On-demand bursting can be disabled only 12 hours after enabling, its hourly fee applies while enabled regardless of attachment, and it does not switch itself off when the tier changes.
- Resizing a VM to escape a cap may restart it and may change other properties. Confirm the procedure for the specific size, as this article does not cover it.
- Figures are version-sensitive. Azure's tables change, so confirm limits against the current pages before committing to a design.
- This article does not cover Azure Elastic SAN, NVMe temporary disks or shared disk behaviour.
Sources
Opened 10 November 2026. Sources behind the corrections reopened 10 November 2026.
- Virtual machine and disk performance
- Azure managed disk types
- Scalability and performance targets for VM disks
- Managed disk bursting
- Enable on-demand bursting
- Performance tiers for managed disks
- Change the performance tier
- Disk performance metrics
- Design for high performance
- Dsv5 series specifications
- Deploy a Premium SSD v2
- Performance plus
- Supported metrics for virtual machines
- az monitor metrics
- az disk
- az vm
- Virtual Machines - Get, REST API
- iostat manual page
This article was originally published on .