Introduction to VHDX on Hyper-V

VHDX is the modern virtual hard disk format used by Hyper-V on Windows Server 2012 and later. It supersedes the older VHD format and brings significant improvements in capacity, reliability, and performance. Understanding the differences between VHD and VHDX, as well as mastering the PowerShell cmdlets for managing VHDX files, is essential for any Hyper-V administrator working on Windows Server 2022.

VHDX Advantages Over VHD

The original VHD format was designed for the era of 32-bit operating systems and modest storage requirements. It supports a maximum disk size of 2,040 GB (approximately 2 TB) and uses 512-byte logical sector sizes, which creates a performance mismatch with modern physical disks that use 4,096-byte (4K) Advanced Format sectors. VHD also lacks protection against corruption that can occur when a host crashes while a write operation is in progress.

VHDX addresses all of these limitations. Its key advantages include:

Maximum disk size of 64 TB. VHDX supports virtual disks up to 64 terabytes, making it suitable for large database servers, data warehouses, and storage-intensive applications that would overflow the 2 TB VHD ceiling.

4K logical sector support. VHDX can use 4,096-byte logical sectors natively, eliminating the sector-size mismatch with Advanced Format physical disks. This reduces the read-modify-write penalty that occurs when a 512-byte virtual sector write maps to a 4K physical sector.

Write journaling. VHDX maintains an internal log of metadata updates. If the host crashes or loses power during a write, Hyper-V can replay the journal on next mount to restore a consistent state, preventing the metadata corruption that sometimes affected VHD disks after unclean shutdowns.

Larger block sizes. VHDX uses a 1 MB block size by default for dynamic disks (compared to 2 MB for VHD), which reduces the overhead of expanding dynamic disks during sequential writes.

Custom metadata. VHDX files can store arbitrary user-defined metadata in their header, which can be read by management tools without mounting the disk.

Creating VHDX Files with PowerShell

The New-VHD cmdlet creates VHDX files from PowerShell. There are three types: fixed, dynamic, and differencing. Fixed disks allocate all specified storage immediately on creation. Dynamic disks start small and grow on demand up to the specified maximum size. Differencing disks store only the changes from a parent disk and are useful for test environments.

Create a fixed VHDX (all storage pre-allocated, best performance):

New-VHD -Path "D:VMsServer01-OS.vhdx" -SizeBytes 100GB -Fixed

Create a dynamic (thin-provisioned) VHDX:

New-VHD -Path "D:VMsServer01-Data.vhdx" -SizeBytes 500GB -Dynamic

When creating a VHDX for use with modern Advanced Format drives, explicitly set the logical sector size to 4096 bytes:

New-VHD -Path "D:VMsServer01-4K.vhdx" -SizeBytes 200GB -Dynamic -LogicalSectorSizeBytes 4096

You can also specify the block size. The default block size for dynamic VHDX is 2 MB in Windows Server 2022. For large sequential workloads, a larger block size can improve throughput:

New-VHD -Path "D:VMsDatabase-Logs.vhdx" -SizeBytes 1TB -Dynamic -BlockSizeBytes 32MB

After creating the VHDX, attach it to an existing VM:

Add-VMHardDiskDrive -VMName "Server01" -Path "D:VMsServer01-Data.vhdx" -ControllerType SCSI -ControllerNumber 0 -ControllerLocation 1

Mounting and Unmounting VHDX Files on the Host

You can mount a VHDX file directly on the Windows Server 2022 host without attaching it to a VM. This is useful for accessing VM disk contents for backup, recovery, or file copy operations. The Mount-VHD cmdlet attaches the VHDX to the host’s disk stack and assigns it a drive letter.

# Mount VHDX read-write
Mount-VHD -Path "D:VMsServer01-OS.vhdx"

# Mount read-only (useful for safe inspection)
Mount-VHD -Path "D:VMsServer01-OS.vhdx" -ReadOnly

# Check which drive letter was assigned
Get-Disk | Where-Object {$_.Location -like "*Server01-OS.vhdx*"} | Get-Partition | Get-Volume

Once mounted, the partitions inside the VHDX appear as regular drives in File Explorer and Disk Management. After completing your work, unmount the VHDX cleanly:

Dismount-VHD -Path "D:VMsServer01-OS.vhdx"

Always dismount before powering the VM back on. If you attempt to start a VM while its VHDX is mounted on the host, Hyper-V will refuse to start the VM with an error indicating the disk is locked.

You can also mount VHDX files from Disk Management in Server Manager by right-clicking in the Disk Management window and selecting Attach VHD, or via the Hyper-V Manager console’s Inspect Disk action.

Resizing VHDX Online

Hyper-V on Windows Server 2022 supports online VHDX expansion for SCSI-attached disks, meaning you can increase the disk size while the VM is running without shutting it down. This is one of the significant operational benefits of using SCSI over IDE controllers for VM disks.

# Resize the VHDX on the host (can be done while VM is running for SCSI disks)
Resize-VHD -Path "D:VMsServer01-Data.vhdx" -SizeBytes 800GB

After expanding the VHDX, you must extend the volume inside the VM. Connect to the VM and use Disk Management or PowerShell to expand the partition:

# Run inside the VM
# Rescan disks to detect size change
Update-Disk

# Extend the volume (replace D with the correct drive letter)
$disk = Get-Disk | Where-Object {$_.Size -gt 700GB}
$partition = $disk | Get-Partition | Where-Object {$_.DriveLetter -eq "D"}
$maxSize = ($partition | Get-PartitionSupportedSize).SizeMax
Resize-Partition -DiskNumber $disk.DiskNumber -PartitionNumber $partition.PartitionNumber -Size $maxSize

Note: VHDX shrinking (reducing size) is not supported online and requires the disk to be offline. Shrinking a partition always carries risk and should be preceded by a backup.

Converting VHD to VHDX

If you have legacy VMs with VHD disks that you want to migrate to the newer format, the Convert-VHD cmdlet performs the conversion. The source VM must be powered off during conversion.

# Convert VHD to VHDX (dynamic)
Convert-VHD -Path "D:VMsLegacyServer.vhd" -DestinationPath "D:VMsLegacyServer.vhdx" -VHDType Dynamic

# Convert and make fixed at the same time
Convert-VHD -Path "D:VMsLegacyServer.vhd" -DestinationPath "D:VMsLegacyServer-fixed.vhdx" -VHDType Fixed

After conversion, update the VM’s disk attachment to point to the new VHDX file:

# Remove old attachment
Remove-VMHardDiskDrive -VMName "LegacyServer" -ControllerType IDE -ControllerNumber 0 -ControllerLocation 0

# Attach new VHDX on SCSI controller (recommended for Windows Server 2022 VMs)
Add-VMHardDiskDrive -VMName "LegacyServer" -Path "D:VMsLegacyServer.vhdx" -ControllerType SCSI -ControllerNumber 0 -ControllerLocation 0

Note that if the VM is Generation 1 with an IDE-attached boot disk, you cannot simply switch to SCSI for the boot disk — Generation 1 VMs boot from IDE. However, converting the VHD to VHDX while keeping it on IDE is still beneficial for the journaling and format advantages.

Compacting Dynamic VHDX Files

Dynamic VHDX files grow as data is written but do not automatically shrink when data is deleted. The Optimize-VHD cmdlet compacts the file by removing blocks that are no longer used inside the VM, recovering the physical disk space on the host.

Before compacting, run a disk optimisation inside the VM to zero-fill the deleted regions. For Windows guests:

# Run inside the VM to zero-fill deleted blocks on each volume
Optimize-Volume -DriveLetter C -ReTrim -Verbose
# If SSD/trim not available, use sdelete to zero free space:
# sdelete64.exe -z C:

Then, with the VM powered off, compact the VHDX on the host:

Mount-VHD -Path "D:VMsServer01-Data.vhdx" -ReadOnly
Optimize-VHD -Path "D:VMsServer01-Data.vhdx" -Mode Full
Dismount-VHD -Path "D:VMsServer01-Data.vhdx"

The -Mode Full parameter performs the most thorough compaction but is the slowest. -Mode Quick skips the interior scan and only reclaims blocks at the end of the file. For maximum space recovery, always use -Mode Full after zeroing free space inside the VM.

Shared VHDX for Guest Clustering

Windows Server 2022 supports Shared VHDX, which allows a single VHDX file to be simultaneously attached to multiple VMs. This is used to provide shared storage to a Windows Server Failover Cluster running inside Hyper-V VMs (a configuration often called guest clustering). Each VM in the cluster attaches to the same VHDX, which acts like a shared SAN LUN.

# Create a shared VHDX (must be fixed, not dynamic)
New-VHD -Path "D:SharedStorageClusterShared.vhdx" -SizeBytes 500GB -Fixed -SupportPersistentReservations

# Attach the shared VHDX to multiple cluster VMs
Add-VMSharedSCSI -VMName "ClusterNode01" -Path "D:SharedStorageClusterShared.vhdx" -ControllerNumber 0 -ControllerLocation 2
Add-VMSharedSCSI -VMName "ClusterNode02" -Path "D:SharedStorageClusterShared.vhdx" -ControllerNumber 0 -ControllerLocation 2

The -SupportPersistentReservations flag enables SCSI-3 Persistent Reservations support, which is required by Windows Failover Clustering for arbitrating disk ownership between nodes. Without persistent reservations, the cluster disk witness and quorum mechanisms will not function correctly.

VHDX Differencing Disks for Test Environments

A differencing VHDX stores only the changes made relative to a parent VHDX, leaving the parent unmodified. This makes differencing disks ideal for test and development environments where you want to quickly spin up multiple VMs from the same base image, or reset a VM to a clean state by simply deleting the differencing disk.

# First, create the parent (base) VHDX and sysprep the VM, then shut it down
# Make the parent read-only to prevent accidental modification
Set-ItemProperty -Path "D:BaseImagesWS2022-Base.vhdx" -Name IsReadOnly -Value $true

# Create a differencing disk for each test VM
New-VHD -Path "D:VMsTestVM01.vhdx" -ParentPath "D:BaseImagesWS2022-Base.vhdx" -Differencing
New-VHD -Path "D:VMsTestVM02.vhdx" -ParentPath "D:BaseImagesWS2022-Base.vhdx" -Differencing

# Attach each differencing disk to its respective VM
Add-VMHardDiskDrive -VMName "TestVM01" -Path "D:VMsTestVM01.vhdx"
Add-VMHardDiskDrive -VMName "TestVM02" -Path "D:VMsTestVM02.vhdx"

To reset a test VM to the clean base state, simply stop the VM, delete its differencing VHDX, create a fresh differencing disk from the same parent, and reattach it. The entire reset operation takes seconds and consumes no additional disk space beyond the initial parent.

The trade-off with differencing disks is that each write must first be looked up in the differencing chain before being satisfied, which adds a small I/O overhead. For production workloads, use fixed VHDX. For test environments where speed of provisioning matters more than peak I/O performance, differencing disks are an excellent choice.

You can inspect the current size and parent path of any VHDX using:

Get-VHD -Path "D:VMsTestVM01.vhdx" | Select-Object Path, VhdType, FileSize, Size, ParentPath, Attached