We're dealing with a Windows Server 2008 R2 Terminal Server (version 6.1.7601) running in a VMware vSphere environment with:
- 4 vCPUs (no overcommitment)
- 32GB RAM allocation
- ~70 concurrent users (recent spike)
The system throws Event ID 1500 when new users attempt to logon during peak periods:
Windows cannot log you on because your profile cannot be loaded...
DETAIL - Insufficient system resources exist to complete the requested service.
Contrary to initial assumptions, this isn't primarily about RAM or CPU. The key constrained resources are:
- Session Paged Pool Memory (default 128MB limit)
- Desktop Heap allocation (default 3MB per session)
- GDI Object Handles (system-wide limit)
We can verify current usage with these PowerShell commands:
# Check session paged pool usage Get-WmiObject -Class Win32_PerfRawData_PerfOS_System | Select-Object PoolPagedBytes # Check desktop heap settings reg query "HKLM\System\CurrentControlSet\Control\Session Manager\Memory Management" /v SessionPoolSize
These registry modifications can significantly increase capacity:
Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management] "SessionPoolSize"=dword:00000040 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\SubSystems] "Windows"=hex(2):25,53,79,73,74,65,6d,52,6f,6f,74,25,5c,73,79,73,74,65,6d,33,32,\ 5c,63,73,72,73,73,2e,65,78,65,20,4f,62,6a,65,63,74,44,69,72,3d,25,53,79,73,\ 74,65,6d,52,6f,6f,74,25,5c,73,79,73,74,65,6d,33,32,5c,43,53,52,53,53,20,53,\ 68,61,72,69,6e,67,53,65,63,74,69,6f,6e,3d,31,32,38,30,30,20,53,65,72,76,65,\ 72,44,6c,6c,3d,62,61,73,65,72,65,66,2c,31,2c,36,30,30,30,30,2c,36,30,30,30,\ 30,20,50,72,6f,66,69,6c,65,43,6f,6e,74,72,6f,6c,3d,4f,66,66,20,4d,61,78,52,\ 65,71,75,65,73,74,54,68,72,65,61,64,73,3d,31,36
Certain applications exacerbate the problem by:
- Creating excessive GDI objects (Excel, Visio)
- Loading large DLLs into each session (CAD software)
- Generating complex window hierarchies (legacy Win32 apps)
Use Process Explorer to identify offenders:
# GDI Objects per process Get-Process | Sort-Object -Property GDIObjects -Descending | Select-Object Name, Id, GDIObjects -First 10
Server Role | Recommended Max Users | Key Constraints |
---|---|---|
Light Office Apps | 80-100 | Desktop Heap |
Medium Business Apps | 50-70 | GDI Objects |
Heavy Engineering Apps | 20-40 | Session Pool |
For monitoring thresholds, implement this PowerShell alert script:
$criticalThreshold = 90 # Percentage $sessionPool = (Get-Counter "\Memory\Pool Paged Bytes").CounterSamples[0].CookedValue $maxPool = (Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management").SessionPoolSize * 1MB if (($sessionPool / $maxPool * 100) -gt $criticalThreshold) { Send-MailMessage -To "admin@domain.com" -From "monitor@domain.com" -Subject "Terminal Server Resource Alert" -Body "Session paged pool usage exceeded $criticalThreshold%" }
This error typically indicates exhaustion of non-paged pool memory in Windows kernel. Unlike regular RAM allocation, this special memory region handles:
- Network connections (SMB/NFS)
- Registry operations
- Security tokens
- Terminal Services session objects
Run these PowerShell commands during peak usage:
# Check non-paged pool usage
Get-Counter '\Memory\Pool Nonpaged Bytes' -Continuous
# Monitor session-specific resources
query session /server:localhost
qwinsta
Add these registry modifications (reboot required):
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management]
"SessionPoolSize"=dword:00000004
"SessionViewSize"=dword:00000030
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters]
"Size"=dword:00000003
While Microsoft's theoretical limit is 16,384 sessions, real-world caps are:
- Light office apps: ~80-100 users
- Medium workloads: ~50-70 users
- Heavy CAD/design: ~30-50 users
Implement folder redirection via GPO:
<GroupPolicy xmlns="urn:schemas-microsoft-com:office:office">
<FolderRedirection>
<Properties action="Update"
path="\\fileserver\profiles\%USERNAME%"
grantExclusive="no"/>
</FolderRedirection>
</GroupPolicy>