Find and Delete Unused Azure Disks and Reduce Storage Costs

One of the major reasons for storage costs you may not be aware of is the presence of unused virtual hard disks (VHDs) in your storage account.  

Unused VHDs can accumulate after migration projects, diagnostic drives of VMs, or backups, but most unused VHDs are orphaned VHDs. Orphaned VHDs are created by deleting VMs in Azure using the Azure Portal or PowerShell.

When you delete a VM, the OS and data disks associated with the VM are not deleted, however, and wind up being left over in the Azure storage account. These unneeded disks take up valuable space in a storage account and wind up incurring charges that most Azure users aren’t aware of. 

You can read more about Azure storage pricing here.

How Unused VHDs Impact Azure Storage Costs

Azure storage costs incurs in two ways: storage account costs (based on redundancy and performance) and storage transaction costs (in the case of standard storage).

When a VHD is unused, storage transaction costs will not grow but storage account costs will continue to show up in your invoice. This can turn out to be expensive, especially if the storage account’s performance type is Premium, as premium storage accounts charge based on the provisioned size.

So, if you provision a 127 GB premium disk but only use 50 GB of it, you will be charged for 127 GB and the price will reflect the closest premium storage SKU, which is P10 (128 GB). Let’s envision the impact of unused VHDs with an example:

Company XYZ had a VM hosting their Web App services. This VM hosted their mission-critical app services and had two premium disks (one P10 and one P20) attached to it along with a GRS Standard disk (127 GB).

Six months ago, XYZ migrated their app services to the Azure PaaS offering, Azure Web App Services, but had not deleted the storage accounts associated with the VM.

The average cost of XYZ's consumed resources for these six months was $1,500 and the unused storage accounted for ~7% of the overall cost.

How to Avoid Creating Orphaned VHDs

There are two ways to avoid creating orphaned VHDs: using Azure Resource Manager and using the Azure Service Manager (classic portal).

1. Azure Resource Manager:

Store all resources with the same life cycle in a single resource group. This includes resources like the VMs IP address, NIC Cards, NSG, storage accounts, and the VM itself.

When the VM needs to be deleted, you can simply delete the resource group. This ensures that all the objects associated with the VM are deleted on one go.

2. Azure Service Manager (classic portal):

When you are deleting Azure VMs from the classic portal, choose the option "delete the attached disks" to ensure the VHDs associated with the VM are also deleted.

Azure Service Manager

If you want to delete the attached VHD, be sure to select that option while deleting a VM.

Find and Delete Unused Azure VHDs

Now that you know how to prevent creating orphan VHDs, you should make finding the unused VHDs in your storage accounts a priority. There are two ways to do this: using GUI or PowerShell.

Deleting with GUI

You can find unused disks in the Azure Storage Explorer console.

Once you drill down to the Blob containers under a storage account, you can see the lease state of the residing VHD (the lease state determines if the VHD is being used by any resource) and the VM to which it is leased out. If you find that the lease state and the VM fields are blank, it means that the VHD in question is unused. 

The screenshot below shows two active VHDs being used by VMs as data and OS disks. The name of the VM and lease state are shown in the "VM Name" and "Lease State" columns, respectively.

Find and Delete Unused VHDs

The next snapshot shows two inactive VHDs with two blank "VM Name" and "Lease State" columns. That means the VHDs are both unused.

Unused VHDs

Now that you know which disks are unused, you can simply select the disk and click on the delete button to delete it. 

Delete Unused VHDs

Another way to use a GUI console to delete unused VHDs is by using the Azure portal

Use the Storage Accounts shortcut on your dashboard and drill down to the Blob container blade under the storage accounts presented there.

Azure PortalNext, go to the properties of each VHD, where you will be able to see the VHD’s lease status and lease state. A lease status of "Unlocked" and a lease state of "Available" indicates that no Azure resources are using this VHD and it can be safely deleted.

Unused VHDs showing a lease status of "Unlocked" and a lease state of “Available.”

It is recommended to use the new ARM Portal as opposed to the Azure Service Manager classic portal to manage storage accounts.

In order to access storage accounts in ASM using ARM, search for “storage accounts (classic)” on the ARM portal and use the same method outlined above to access the VHDs.

The process becomes a bit simpler for managed disks as managed VHDs show up as a top-level item and you don't have to drill down through storage accounts and containers to find them.

Having said that, you still have to go to each managed VHD and look for the “Disk State” and “Owner VM” fields which, if the VHD is unused, will show “Unattached” and blank respectively. Managed unused VHDs will show up as in the picture below:

Managing unused VHDs

Deleting with PowerShell

Although there are GUI options to delete unused VHD disks, it becomes cumbersome as you scale your storage accounts and VHDs. You have to drill down to each storage account and blob container or individual VHDs which might become hectic.

Also, sometimes you would notice that the locked lease of the disks are not released automatically (and hence giving false negatives on whether the disk is unused) and there is a whole article on troubleshooting that.

This is why a lot of people prefer using scripting tools like PowerShell to find and delete these unused VHDs.

A PowerShell script is the best choice to delete these unused storage disks.

  • Step 1: Start by logging into the Azure Resource Manager account. The following cmdlet will prompt you for Azure login credentials:
  • Step 2: Get all the information on the storage accounts:
    $SA = Get-AzureRmStorageAccount
  • Step 3: Get the information about the managed and the unmanaged VHDs:
    $UMD = $SA | Get-AzureStorageContainer | Get-AzureStorageBlob | Where {$_.Name -like '*.vhd'} 
    $UMVHDS = $UMD | Where {$_.ICloudBlob.Properties.LeaseStatus -eq "Unlocked"} 
    $MVHDS = Get-AzureRmDisk
    $MVHD = $MVHDS | Where {$_.OwnerId -eq $null}
  • Step 4: The information about the VHDs will be exported into separate CSV files for managed and unmanaged Disks. Once you check that information, you can determine if you want to delete the VHD or not. To delete:
    $UMVHDS | Remove-AzureStorageBlob
    $MVHD | Remove-AzureRmDisk

There are two scripts, specifically UnusedVHDRead.ps1 and UnusedVHDReadandDelete.ps1. Run the second script only if you are sure you want to delete the VHDs. You can find the script files here.

*Please Note: The scripts are provided as-is and NetApp does not bear any responsibility for these scripts.


Deleting unused VHDs, especially the prolific orphaned VHDs is an easy way to keep your Azure storage costs in check. Having said that, it is recommend to err on the side of caution when deleting VHDs since they might contain important data that you have not backed up.

A good way to determine if a VHD is important or not would be to mount the VHD on a VM and ensure that it is safe to delete before running any script on them or deleting them from the GUI console.

Want to get started? Try out Cloud Volumes ONTAP today with a 30-day free trial.