skip to content

IIS

IIS is the Windows web server: sites and bindings define what it listens on, application pools give each app its own worker process with its own identity and recycling policy, and ASP.NET/.NET Core hosting rides on top of it. Interviewers ask about it in Windows shops to check whether I can diagnose a recycling storm, an identity/permission failure or a binding conflict rather than just click through the management console.

on this pageshow

questions

5

In IIS, what is an application pool, and how does it relate to the w3wp.exe worker process that actually runs your web application?

level: juniorimportance: must knowfreq 74%

answer

  1. the unit of isolation, not the site
  2. one worker process per pool
  3. kernel queue, then a process is started
  4. identity, recycling and pipeline live here
  5. w3wp.exe -ap "PoolName"

basics

~20 s

An IIS application pool is the isolation boundary for one or more web applications. IIS runs each pool in its own w3wp.exe worker process, so a crash, a recycle, or an identity change affects only the applications assigned to that pool.

solid answer

~40 s

An application pool is a named configuration object in IIS that defines a process boundary: it carries the identity the code runs as, the managed pipeline mode (Integrated or Classic), the .NET CLR version, 32- vs 64-bit, recycling rules and the idle time-out. Requests are accepted in the kernel by HTTP.sys and queued per pool; the Windows Process Activation Service starts a `w3wp.exe` worker process for that pool on demand, and that process loads the IIS modules and executes your application. The mapping people get wrong is that it is one worker per *pool*, not per site — a single site's applications can sit in different pools, and one pool can host applications from several sites. Everything sharing a pool shares its memory, its identity and its crash.

go deeper

for a junior

Be able to say plainly that the application pool is the configuration for a worker process, that IIS runs one w3wp.exe per pool, and that applications sharing a pool share its fate.

for a middle

Explain the HTTP.sys queue, WAS starting the worker on demand, and which settings live on the pool rather than the site — identity, pipeline mode, CLR version, bitness, recycling.

for a senior

Show that you reason about blast radius: which applications share a process, what a memory-limit recycle or a crash takes down with it, and the memory cost of splitting pools for isolation.

for a principal

Own the hosting-density trade for a whole fleet — how many pools per server, when isolation justifies the per-worker memory overhead, and when the answer is to stop co-hosting on IIS at all.

## The three layers behind one request IIS is not a single process. A request to an IIS-hosted application passes through three distinct pieces before any of your code runs. **HTTP.sys** is a kernel-mode driver that owns the TCP ports. It listens, parses the request line and headers, matches the URL against the set of registered URL prefixes, and places the request into a *request queue*. There is one request queue per application pool. Because HTTP.sys is in the kernel, it can accept connections and even serve cached responses while no user-mode process for that application is running at all. **WAS** — the Windows Process Activation Service — watches those queues. When a request lands in a queue that has no worker process behind it, WAS starts one. The World Wide Web Publishing Service (W3SVC) sits alongside it and owns the HTTP-specific configuration, handing the port and prefix registrations to HTTP.sys. **w3wp.exe** is the worker process. It loads the native IIS modules, loads the CLR if the application is managed, and runs your request pipeline. This is the process you attach a debugger to, the process that shows up in Task Manager eating memory, and the process that dies when your application faults. ## What the pool actually owns The application pool is the configuration object that describes that worker process. Its settings live in `applicationHost.config` under `<applicationPools>`: ```xml <add name="ContosoPool" managedRuntimeVersion="v4.0" managedPipelineMode="Integrated" enable32BitAppOnWin64="false"> <processModel identityType="ApplicationPoolIdentity" idleTimeout="00:20:00" /> <recycling><periodicRestart time="1.05:00:00" /></recycling> </add> ``` The pool decides: the **identity** the code runs as (and therefore every file, share and database it can reach); the **managed pipeline mode**, Integrated or Classic, which decides whether managed modules see every request or only ASP.NET-mapped ones; the **CLR version**, including the value `No Managed Code` used for ASP.NET Core; **bitness**; **recycling** rules and the **idle time-out**; **rapid-fail protection**; and the request **queue length**. ## Sites, applications, and pools are three different things A **site** is a set of bindings (protocol, IP, port, host name) plus a root application. An **application** is a virtual path such as `/shop` mapped to a physical directory, and every application is assigned to exactly one application pool. A **virtual directory** is just a path alias inside an application and has no process of its own. That means the relationship is many-to-many in the useful direction: one site can spread its applications across several pools, and one pool can host applications drawn from several sites. Counting worker processes by counting sites is the classic beginner error. ## One process per pool — with two exceptions By default a running pool has exactly one `w3wp.exe`. Two things change that. A **web garden** (`maxProcesses` greater than 1) runs several workers for the same pool; requests are spread across them, which breaks any in-memory session or cache and is rarely the right answer today. And during an **overlapped recycle** you briefly see two workers for one pool while the new one warms up and the old one drains. To see the mapping live, `appcmd list wp` prints each running worker with its pool, and the worker's own command line carries `-ap "PoolName"`, which is why adding the Command Line column in Task Manager tells you instantly which pool a hungry `w3wp.exe` belongs to. ## Why the boundary is the point Everything in one pool shares one address space. An unhandled exception that takes down the process takes down every application in that pool. A memory-limit recycle triggered by one leaky application discards the in-memory caches and sessions of its neighbours. The identity is shared, so granting one application write access to a folder grants it to all of them. A stuck thread pool starves them all. Conversely, separating applications into their own pools buys real isolation at the cost of memory: each additional worker process carries its own CLR, its own JIT-compiled code and its own caches, typically tens to a couple of hundred megabytes before your application allocates anything. One consequence worth memorising for diagnosis: if a pool is stopped — either manually or by rapid-fail protection after repeated startup failures — HTTP.sys still accepts the connection and answers **503 Service Unavailable**, not 404. A 503 that appears instantly, with nothing at all in the application's own logs, almost always means the request never reached a worker process.

  • If the application pool is stopped, what does a client actually get back, and why?
    A 503 Service Unavailable, returned almost instantly. HTTP.sys accepts the connection in the kernel and finds the pool's request queue disabled or with no worker behind it, so it answers itself. Nothing reaches your code, which is why the application log is silent — you look in the System event log and at the pool's state instead.
  • What is a web garden in IIS, and why is it usually a bad idea?
    Setting an application pool's maximum worker processes above one runs several `w3wp.exe` instances for the same pool, with requests spread across them. It sidesteps nothing that matters on modern hardware — a single worker already uses all cores — while multiplying memory and destroying any in-process session state or cache, since consecutive requests from one user can land in different processes.
  • What is the practical difference between Integrated and Classic managed pipeline mode?
    In Integrated mode the managed modules are merged into the single IIS pipeline, so ASP.NET modules such as authentication and rewriting see every request, including static files. Classic mode reproduces the old ISAPI behaviour: managed code runs only for extensions mapped to ASP.NET. Classic exists for legacy applications whose configuration or module assumptions break under Integrated.

saying these in an interview costs you the question

  • Says IIS starts one w3wp.exe per website
  • Treats application pool and website as the same object
  • Thinks IIS itself executes the managed application code
  • Assumes two apps in one pool are isolated from each other
  • Expects 404 rather than 503 when a pool is stopped

context

open as a page

Users of an ASP.NET application hosted on IIS report being randomly signed out during the day, and the first request each morning takes about thirty seconds. How do IIS application pool recycling and the idle time-out explain both symptoms, and what would you change?

level: middleimportance: must knowfreq 63%

basics

~20 s

Both symptoms come from the worker process going away. The IIS application pool idle time-out kills w3wp.exe after 20 minutes with no requests, and periodic recycling restarts it roughly every 29 hours, discarding in-process session state and forcing a cold start on the next request.

open as a page

An application hosted on IIS gets Access Denied both when writing to a local folder and when reading a UNC file share, though the same code works when you run it interactively as yourself. Which identity is the request actually running under, and how do you grant each of those accesses correctly?

level: seniorimportance: should knowfreq 54%

basics

~20 s

By default the code runs as the application pool's virtual account, named IIS APPPOOL<PoolName>. Grant local folder access to that name directly. It has no network identity, so a UNC share must instead be granted to the server's computer account — or the pool switched to a domain account.

open as a page

You add a second website to an IIS server bound to port 443 and it will not start; the System event log says the WWW Publishing Service could not register the URL prefix. What does an IIS binding consist of, and how would you diagnose and resolve the conflict?

level: seniorimportance: should knowfreq 46%

basics

~20 s

An IIS binding is the tuple protocol, IP address, port and host name (plus a certificate for HTTPS). Two sites whose tuples collide cannot both register their prefix with HTTP.sys, so the second fails to start. Give them distinct host names — with SNI enabled for HTTPS — or distinct IPs or ports.

open as a page

The ASP.NET Core Module in IIS supports two hosting models, selected by the hostingModel attribute in web.config as inprocess or outofprocess. How do the two differ at runtime, and when would you choose each?

level: middleimportance: nice to knowfreq 38%

basics

~20 s

Out-of-process, the IIS module launches your app as a separate process running Kestrel on a local port and reverse-proxies each request to it. In-process, it loads the runtime inside w3wp.exe and the app serves through IIS directly, which removes the extra hop and is faster.

open as a page