Web Gardens in IIS refer to application pools configured with multiple worker processes (w3wp.exe). While this feature can improve performance by distributing requests across processes, it's not a silver bullet. Let's examine the technical implications:
Web Gardens excel in scenarios where:
- Handling CPU-bound operations with parallel processing
- Isolating unstable components (one crashing worker won't affect others)
- Scaling on multi-core servers without full server farms
// Example: Configuring Web Gardens in applicationHost.config
<applicationPools>
<add name="MyAppPool">
<cpu smpAffinitized="true" smpProcessorAffinityMask="3" />
<processModel maxProcesses="4" />
</add>
</applicationPools>
Despite benefits, Web Gardens introduce several challenges:
Memory Overhead
Each worker process maintains its own memory space. For memory-intensive apps, this can quickly exhaust server resources:
// PowerShell to monitor memory usage
Get-Process w3wp | Sort-Object WS -Descending |
Select-Object Id, ProcessName, WS, VM | Format-Table -AutoSize
Session State Complications
In-process sessions become unreliable as requests may hit different workers:
// ASP.NET workaround using out-of-process session
<sessionState
mode="SQLServer"
sqlConnectionString="Data Source=.;Integrated Security=True"
timeout="20" />
Cache Duplication
Each worker maintains separate cache instances, potentially wasting memory storing duplicate data.
When benchmarking Web Gardens, consider:
- Run load tests with tools like JMeter or WebLoad
- Monitor kernel-mode vs user-mode CPU usage
- Track context switching rates (use PerfMon or ETW traces)
// Sample WebTest config for JMeter
<TestPlan>
<ThreadGroup>
<num_threads>100</num_threads>
<ramp_time>60</ramp_time>
</ThreadGroup>
<HTTPSampler>
<domain>yourserver.com</domain>
<path>/stresspage.aspx</path>
</HTTPSampler>
</TestPlan>
For high-traffic scenarios, consider:
- ARR (Application Request Routing) with server farms
- Kubernetes-based container orchestration
- Cloud-native auto-scaling solutions
The optimal worker count depends on your specific workload characteristics. Start with 2-4 workers and measure carefully before scaling further.
Enabling multiple worker processes (web gardens) in IIS creates separate w3wp.exe instances for an application pool. This seems brilliant at first glance - automatic request distribution, process isolation, and potential performance gains. But here's what really happens under the hood:
// Sample PowerShell to check current worker count
Import-Module WebAdministration
Get-ChildItem IIS:\AppPools | Select-Object Name, @{n="WorkerCount";e={$_.processModel.workerProcesses.Count}}
Each worker process loads a complete copy of your application. For a .NET Core app using 500MB RAM, 10 workers = 5GB consumption. Consider this memory replication formula:
TotalMemory = (BaseProcessSize + AppMemory) * WorkerCount
We once deployed a web garden with 4 workers for a high-traffic API. The server ran out of memory within hours because each worker loaded 1.2GB of framework libraries.
Web gardens break in-process session state. You'll see users randomly logged out because requests hit different workers. The solutions:
// Configure out-of-process session in web.config
<sessionState
mode="SQLServer"
sqlConnectionString="Data Source=myServer;Integrated Security=True"
timeout="20" />
More workers ≠ linear performance gains. We benchmarked a load-balanced scenario:
Workers | Requests/sec | Avg CPU% |
---|---|---|
1 | 850 | 75% |
2 | 1200 | 83% |
4 | 1450 | 94% |
The law of diminishing returns kicks in hard after 2-3 workers.
They're perfect for:
- Legacy COM components that aren't thread-safe
- Applications with memory leaks (contain crash impact)
- CPU-bound workloads where requests block significantly
After troubleshooting 50+ production deployments, our heuristic is:
OptimalWorkers = min(CPU_Cores - 1, ceil(ConcurrentUsers/1000))
Always test with your actual workload. The IIS team didn't default to multiple workers because one properly tuned process usually outperforms several competing ones.