Introduction to Storage Tiering with Storage Spaces on Windows Server 2019
Storage Tiering in Windows Server 2019 allows a single Storage Space virtual disk to span multiple classes of physical drives — such as NVMe or SSD drives for a “Performance” tier and HDD drives for a “Capacity” tier. Windows automatically moves frequently accessed (hot) data to the fast tier and infrequently accessed (cold) data to the slow tier. This gives you near-SSD performance for hot data at a fraction of the cost of an all-flash storage system, while retaining economical HDD capacity for bulk data.
Storage Tiering works through a background service (the Storage Tiers Management task) that analyses access patterns every 24 hours by default and moves data between tiers accordingly. You can also manually trigger tier optimisation at any time. Storage Tiering requires Windows Server 2019 Standard or Datacenter edition and does not require a failover cluster — it works on standalone servers as well as within Storage Spaces Direct clusters.
Hardware Preparation and Storage Pool Creation
Install a mix of SSD (or NVMe) and HDD drives in the server. Windows Server 2019 automatically detects the media type. Verify detected drives and their media types:
Get-PhysicalDisk | Select FriendlyName, MediaType, Size, HealthStatus, OperationalStatus
If media type is not automatically detected correctly, set it manually:
Get-PhysicalDisk -FriendlyName "WDC WD40EFRX*" | Set-PhysicalDisk -MediaType HDD
Get-PhysicalDisk -FriendlyName "Samsung SSD 870*" | Set-PhysicalDisk -MediaType SSD
Create a storage pool from all available physical disks (exclude the OS disk):
$disks = Get-PhysicalDisk -CanPool $true
New-StoragePool -FriendlyName "TieredPool" -StorageSubSystemFriendlyName (Get-StorageSubSystem).FriendlyName -PhysicalDisks $disks
Verifying Storage Tiers
After creating the storage pool, Windows Server 2019 automatically creates storage tiers named “Performance” (SSD/NVMe) and “Capacity” (HDD) if both media types are present in the pool. Verify the tiers were created:
Get-StorageTier | Select FriendlyName, MediaType, AllocatedSize, Size, ResiliencySettingName
View the pool and its composition:
Get-StoragePool -FriendlyName "TieredPool" | Get-PhysicalDisk | Select FriendlyName, MediaType, Size
Check available capacity in each tier:
Get-StorageTier | Select FriendlyName, @{N='FreeSpace(GB)';E={[math]::Round(($_.Size - $_.AllocatedSize)/1GB,2)}}, @{N='Size(GB)';E={[math]::Round($_.Size/1GB,2)}}
Creating a Tiered Virtual Disk
Create a tiered virtual disk specifying how much capacity to allocate from each tier. This example creates a 600 GB tiered volume: 100 GB from SSD (Performance) and 500 GB from HDD (Capacity), with two-way mirror resiliency:
$performanceTier = Get-StorageTier -FriendlyName "Performance"
$capacityTier = Get-StorageTier -FriendlyName "Capacity"
$pool = Get-StoragePool -FriendlyName "TieredPool"
New-VirtualDisk -StoragePoolFriendlyName "TieredPool" -FriendlyName "TieredVolume01" -StorageTiers @($performanceTier, $capacityTier) -StorageTierSizes @(100GB, 500GB) -ResiliencySettingName Mirror -WriteCacheSize 10GB -AutoWriteCacheSize $false
The -WriteCacheSize parameter configures an SSD write-back cache layer on top of the tiered volume. Data written to the cache is destaged to the appropriate tier asynchronously, which dramatically improves write performance for random I/O workloads.
Initialising and Formatting the Volume
After creating the virtual disk, initialise, partition, and format it:
$vdisk = Get-VirtualDisk -FriendlyName "TieredVolume01"
$disk = $vdisk | Get-Disk
Initialize-Disk -Number $disk.Number -PartitionStyle GPT
New-Partition -DiskNumber $disk.Number -UseMaximumSize -AssignDriveLetter
Format-Volume -DriveLetter E -FileSystem ReFS -NewFileSystemLabel "TieredData" -AllocationUnitSize 65536 -Confirm:$false
ReFS is recommended for tiered storage because it integrates with the Storage Spaces integrity scrubbing mechanism and supports block-cloning for efficient VM checkpoint operations.
Running Tier Optimisation Manually
Storage tiering optimisation runs automatically every day at 1 AM via a scheduled task. To trigger it manually:
Optimize-StoragePool -FriendlyName "TieredPool"
Or optimise a specific virtual disk’s tiers:
Invoke-Item "C:WindowsSystem32TasksMicrosoftWindowsStorage Tiers ManagementStorage Tiers Optimization"
Using the scheduled task trigger in PowerShell:
Get-ScheduledTask -TaskName "Storage Tiers Optimization" | Start-ScheduledTask
Monitoring Tier Usage
Check how much data is currently in each tier of a virtual disk:
Get-StorageTierSupportedSize -FriendlyName "TieredVolume01"
View current tier allocation for a virtual disk:
Get-VirtualDisk -FriendlyName "TieredVolume01" | Get-StorageTier | Select FriendlyName, AllocatedSize
Check overall storage pool health and available capacity:
Get-StoragePool -FriendlyName "TieredPool" | Select FriendlyName, HealthStatus, OperationalStatus, @{N='FreeSpace(GB)';E={[math]::Round(($_.Size - $_.AllocatedSize)/1GB,1)}}
Storage Tiering with Storage Spaces in Windows Server 2019 delivers a compelling cost-performance balance, automatically managing hot and cold data placement without administrator intervention once configured.