Table of Contents
Why the pagefile matters
In Azure Virtual Desktop (AVD), the Windows pagefile is far more than a legacy configuration item.
In multi-session environments, memory pressure is a daily reality:
- Dozens of concurrent user sessions
- Multiple Office applications per user
- Teams, Outlook, browsers, plugins, etc.
Even when sizing virtual machines generously, RAM exhaustion will happen. When that moment arrives, Windows relies on the pagefile to:
- Avoid session crashes
- Prevent black screens
- Stabilize memory commit limits
- Allow applications to allocate virtual memory
If the pagefile is missing, misconfigured, or located on the wrong disk, the results are often:
- Failed logons without clear errors
- Session host instability under load
- “Out of memory” conditions even with free RAM
What changed with Azure v6 VM SKUs
On v5 and earlier Azure VM SKUs, the temporary disk was:
- Automatically initialized
- Formatted
- Made available as a drive (usually D:), ready for use at first boot
This meant you could reliably assume the temp disk existed and had a usable filesystem without doing any setup – perfect for placing the Windows pagefile on it.
With the newer v6 VM SKUs, this assumption no longer holds.
According to Microsoft’s Temp NVMe Disks FAQ:
“Unlike the previous D/E series VMs, the new v6 VMs come with raw, unformatted NVMe disks. Customers should initialize and format the disks into a file system of their preference after the VM starts up.“
In other words:
- Azure now presents the temp NVMe disk as raw storage: no filesystem, no drive letter
- The guest OS must initialize, format, and mount it before anything (including the pagefile) can be placed on it
- After stop/deallocate or maintenance events, the VM boots with the NVMe disks unformatted again, so automation must run on every start to reinitialize them before use
This change was introduced to support higher-performance NVMe storage on v6 VMs (optimized for throughput and IOPS), but it breaks the old assumption that the temp disk is usable immediately upon startup.
Design goals for a reliable AVD pagefile solution
When implementing pagefile automation for Azure Virtual Desktop, especially on v6 NVMe-based VM SKUs the solution must be designed for far more than just disk detection. A reliable approach must account for AVD agent startup behavior, Windows boot timing, and mandatory reboots required for pagefile activation.
Design goals are therefore:
- Support both v5 and v6 VM SKUs
- Detect classic temp disks and new NVMe disks
- Automatically initialize and format RAW disks
- Recreate the temp disk after VM deallocation or scaling
- Fall back safely to C: if no temp disk is available (e.g. SKU Change from Standard_E8ds_v6 to Standard_E8s_v6 )
- Prevent infinite reboot loops
- Provide detailed logging for troubleshooting
⚠️ Prevent race conditions with the AVD agent
This point is critical and often underestimated: the Azure Virtual Desktop services (RDAgent and RDAgentBootLoader) start early in the Windows boot process. If these services become available before the pagefile is fully configured and activated, user logins may already be accepted. These sessions are then established successfully, only to be immediately disconnected or logged out once the mandatory reboot for pagefile activation occurs.
A correct AVD pagefile solution must therefore ensure: No user logins are possible before pagefile configuration is finished!
Script Overview
This script provides a pagefile configuration mechanism and can be accessed in the repository below.
🧬 azure-avd-pagefile-automation
High-Level Workflow
- Race Condition Protection
• Prevents AVD user logins before pagefile configuration is completed
• Stops AVD services during configuration - Detect Temp Disk
Supports both Azure temp disk types
• v5 SKUs: Msft Virtual Disk
• v6 SKUs: Microsoft NVMe Direct Disk v2 - Disk Initialization
• Detects whether the temp disk is already usable
• Automatically initializes disk if required
• Removes CD-ROM drive letter (D:) if present
• Initializes disk using GPT
• Formats disk as NTFS
• Creates and mounts the D: drive - Pagefile Configuration
• Automatically configures pagefile on D: (preferred when temp disk is available)
• C: (fallback if no temp disk exists) - Safe Reboot Handling
• Detects when a reboot is required to activate the pagefile
• Uses registry-based tracking to prevent infinite reboot loops
• Resume configuration after restart - Disk Wipe Detection & Self-Healing
• Detects temp disk loss after VM deallocation or Host maintenance
• Reinitializes the disk and configures pagefile - Finalization
• Starts services only when the system is fully ready.
• Cleans up all registry markers after successful completion.
Pagefile Configuration Modes
The script supports two models.
System-managed (recommended)
|
1 |
$UseManagedPagefile = $true |
Windows dynamically adjusts the pagefile size based on workload demands. This approach is generally considered the best option for multi-session Azure Virtual Desktop environments and has also been confirmed through analysis by GO-EUC.
Fixed size (optional)
|
1 2 3 |
$UseManagedPagefile = $false $FixedInitialSizeMB = 16384 $FixedMaxSizeMB = 32768 |
Useful when enforcing strict memory limits.
Automatic fallback logic
The most critical feature is fallback protection.
If the VM boots and:
- The temp disk does not exist
- D: is missing
- The NVMe disk is not present
The script automatically:
- Switches pagefile back to C:
- Keeps the session host online
- Avoids failed logins
Once the temp disk reappears (after redeploy or scaling):
- D: is reinitialized
- Pagefile is moved back automatically
No manual intervention required.
Reboot loop protection
Because pagefile changes require a reboot, the script includes:
|
1 |
$MaxRebootAttempts = 3 |
State is tracked via registry:
|
1 |
HKLM:\SOFTWARE\AVD\AVDPagefileSetup |
This prevents:
- Endless reboot cycles
- Broken scaling operations
- Hosts stuck in “Unavailable” state
If the limit is reached, the system safely exits and brings AVD services back online.
Logging and troubleshooting
All operations are logged to:
|
1 |
C:\Windows\Temp\AVDPagefileSetup\avd_nvme_pagefile.log |
You get full visibility into:
- Disk detection
- Formatting
- Pagefile changes
- Reboot attempts
- Fallback decisions
This makes root-cause analysis extremely easy when troubleshooting session host behavior.
Example – Log File Output:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
[2026-01-27 23:30:26] === Script Start === Marker: | RebootCount: 0 [2026-01-27 23:30:26] Checking 'CSECompleted' registry value existence... [2026-01-27 23:30:26] 'CSECompleted' registry value exists. [2026-01-27 23:30:27] Current pagefile state: D: NONE | C: NONE [2026-01-27 23:30:33] Configuration needed: Temp disk available but D: drive not initialized [2026-01-27 23:31:11] Stopped RDAgent and set startup to Manual [2026-01-27 23:31:11] Stopped RDAgentBootLoader and set startup to Manual [2026-01-27 23:31:12] CD-ROM detected on D:, removing drive letter [2026-01-27 23:31:12] Removed D: from CD-ROM [2026-01-27 23:31:14] Found temp disk: Disk 1 [2026-01-27 23:31:14] Initializing temp disk as GPT [2026-01-27 23:31:14] Creating partition and formatting as D: [2026-01-27 23:31:18] Temp disk initialized and formatted as D: [2026-01-27 23:31:18] D: drive verified and accessible [2026-01-27 23:31:18] Target drive D: exists: True [2026-01-27 23:31:18] Pagefile file on D: exists: False [2026-01-27 23:31:18] Configuration needed: True | Reboot needed: True [2026-01-27 23:31:18] Configuring pagefile on D: [2026-01-27 23:31:18] Setting system-managed pagefile on D: [2026-01-27 23:31:18] Pagefile registry updated successfully [2026-01-27 23:31:18] Reboot attempt #1 of 3 [2026-01-27 23:31:18] Initiating system reboot to activate pagefile on D: [2026-01-27 23:31:53] === Script Start === Marker: 1 | RebootCount: 1 [2026-01-27 23:31:53] Checking 'CSECompleted' registry value existence... [2026-01-27 23:31:53] 'CSECompleted' registry value exists. [2026-01-27 23:31:53] Current pagefile state: D: EXISTS | C: NONE [2026-01-27 23:31:55] D: drive with temp disk detected and pagefile is configured [2026-01-27 23:31:55] Pagefile configuration is already optimal. Ensuring services are running. [2026-01-27 23:31:55] Started service RDAgent [2026-01-27 23:31:56] Started service RDAgentBootLoader [2026-01-27 23:31:56] === Setup Complete === AVD Session Host ready for connections |
Integration
To ensure reliable operation, the pagefile script must run at every system startup. For these reason, the script must not be executed only once during image creation or through a Custom Script Extension during virtual machine provisioning. It must instead run automatically at every system startup to ensure consistent and reliable pagefile configuration The recommended approach is to use a Windows Scheduled Task triggered at startup.
Integration with Packer
- Copy the script into the image
|
1 2 3 4 5 6 |
provisioner "file" { sources = [ "scripts/900_Finalize/Set-Pagefile.ps1" ] destination = "C:/PackerBuild/" } |
2. Create a scheduled startup task
|
1 2 3 4 5 6 7 8 9 |
provisioner "powershell" { inline = [ "$action = New-ScheduledTaskAction -Execute 'PowerShell.exe' -Argument '-NoProfile -ExecutionPolicy Bypass -File C:\\PackerBuild\\Set-Pagefile.ps1'", "$trigger = New-ScheduledTaskTrigger -AtStartup", "$principal = New-ScheduledTaskPrincipal -UserId 'SYSTEM' -RunLevel Highest", "$settings = New-ScheduledTaskSettingsSet -StartWhenAvailable", "Register-ScheduledTask -TaskName 'Packer-SetPagefile' -Action $action -Trigger $trigger -Principal $principal -Settings $settings -Force" ] } |
Custom Script Extension Dependency
In many Azure Virtual Desktop deployments, virtual machines are provisioned using Terraform or Bicep and finalized using an Azure Custom Script Extension (CSE). Typical tasks executed by the CSE include:
- Installation and onboarding of antivirus or EDR agents
- Monitoring and management agents
- Product activation
- Final system configuration steps
These actions are usually required before the session host becomes operational.
Why this matters for pagefile configuration
Because the Custom Script Extension runs during VM provisioning, it introduces an important dependency:
- The pagefile script must not start while the CSE is still running.
Running the pagefile configuration in parallel with the Custom Script Extension can cause multiple issues:
- Competing reboots
- Failed agent registrations
- Partially applied system settings
In worst cases, the VM may end up in an inconsistent provisioning state.
For that reason, the pagefile automation must only run after all CSE-based configuration tasks have completed successfully.
How this dependency is handled
To ensure correct execution order, the script includes an explicit CSE completion check. If CSE is not used in your environment, this section of the script can be removed without impact.
|
1 2 3 4 5 6 7 8 9 10 11 12 |
# ========================= # CSE Check (Azure Custom Script Extension) # ========================= $CseRegPath = "HKLM:\SOFTWARE\AVD\CSE" $CseRegName = "CSECompleted" Write-Log "Checking '$($CseRegName)' registry value existence..." if (-not (Get-ItemProperty -Path $CseRegPath -Name $CseRegName -ErrorAction SilentlyContinue)) { Write-Log "'$($CseRegName)' registry value does not exist. Exiting." exit 0 } |
The logic verifies the presence of a dedicated registry value that is written by the Custom Script Extension once all provisioning tasks are finished. Only when this registry key exists does the pagefile script continue execution.
If the value is not found:
- The script exits gracefully
- No disk changes are made
- No reboot is triggered
This guarantees that:
- Terraform or Bicep provisioning completes cleanly
- All agents are installed and activated first
- Pagefile configuration runs only on a fully prepared system
Why the Custom Script Extension cannot be used alone
You might be wondering when implementing this script:
Why not simply use an Azure Custom Script Extension instead of a scheduled task?
The reason is straightforward but very important. The Custom Script Extension is executed only once, during the initial provisioning of the virtual machine.
After that:
- it is not triggered again on reboot
- it does not run after deallocation
- it does not run when scaling plans start a VM
- it does not react to temp disk wipes
This behavior makes the Custom Script Extension unsuitable for managing components that are not persistent, such as the Azure temp disk. As a result, the VM may boot without a valid pagefile, leading to login instability and performance issues.
Final Thoughts
I hope this article helps anyone who is currently onboarding or migrating Azure Virtual Desktop environments to v6 VM SKUs and wants to achieve a faster and smoother onramp.
The move to NVMe-based temp disks brings clear performance advantages, but it also introduces fundamental behavioral changes compared to previous VM generations. Unfortunately, Azure currently does not provide a built-in mechanism to automatically initialize these disks or handle pagefile placement in a reliable way.
As a result, customers are left to implement their own automation and safeguards, especially for scenarios involving multi-session workloads, scaling plans, and frequent deallocation events.
While this can be somewhat frustrating, understanding these changes and designing around them is essential for building stable AVD environments on v6 SKUs. Once properly automated, the platform performs extremely well and benefits significantly from the new NVMe architecture.
If you have ideas for improvement, find edge cases, or want to enhance the script further, feel free to reach out to me directly or submit a pull request on GitHub. Contributions, feedback, and real-world experiences are always welcome.