IIS — Internet Information Services and Hosting .NET Applications
In short: Microsoft's Windows web server.
- It hosts static sites, ASP.NET Framework apps (Web Forms, MVC 5, Web API 2, WCF), ASP.NET Core apps via the ASP.NET Core Module, and through modules/ARR can proxy to Node.js, Next.js or other servers.
- It provides bindings, HTTPS, authentication (including Windows auth), compression, caching, URL rewriting and logging.
In short: A group of one or more applications served by the same worker process (w3wp.exe) with shared settings: .NET CLR version, pipeline mode, identity, recycling and limits.
- Pools isolate applications — a crash, memory leak or recycle in one pool doesn't affect apps in other pools — and define the security identity the app runs as.
In short: The IIS worker process.
- Each application pool runs in its own w3wp.exe (or several in a web garden);
- it hosts the IIS pipeline, modules and your application code (including in-process ASP.NET Core apps).
- You attach the Visual Studio debugger to w3wp.exe to debug IIS-hosted apps and see it in Task Manager with the pool identity as the user.
In short: Install the .NET Hosting Bundle on the server, dotnet publish -c Release, create an app pool with "No Managed Code", create a site pointing to the publish folder with bindings and a certificate, grant the pool identity read permissions (write for logs/uploads), set environment variables (ASPNETCORE_ENVIRONMENT, connection strings) and browse.
- The published web.config configures the ASP.NET Core Module (in-process by default).
In short: A site is the top-level website with bindings and a root folder.
- An application is a sub-path that is its own ASP.NET application (own web.config root, can use a different app pool).
- A virtual directory just maps a URL path to a physical folder inside an application without being a separate app.
In short: In-process runs the app inside the IIS worker process using IIS's HTTP server — no extra network hop, best performance, but only one ASP.NET Core app per pool.
- Out-of-process runs the app as a separate Kestrel process with IIS (ANCM) forwarding requests over loopback — slower, but multiple apps per pool and Kestrel-specific features.
- Configured with
hostingModelin web.config /AspNetCoreHostingModelin the project.
In short: IIS periodically (default every 29 hours), on configuration changes, memory/request limits or on demand starts a new worker process and shuts down the old one.
- It frees leaked memory and refreshes the app, but in-memory state is lost (InProc session, MemoryCache, static data) and the first request after startup may be slow.
- Schedule recycles off-peak, use out-of-process state and warm-up (Application Initialization).
In short: A per-pool virtual account (IIS AppPool\<PoolName>) created automatically, with minimal privileges.
- Grant it NTFS rights on the site folders (
icacls ... /grant "IIS AppPool\ShopPool":RX), and for SQL Server with Windows authentication create a login for it locally or for the computer account (DOMAIN\SERVER$) when SQL is remote — or use a dedicated domain service account.
In short: The app failed to start.
- Check Event Viewer (Application log) for the ANCM and app exceptions, enable
stdoutLogEnabledwith a writable logs folder, rundotnet YourApp.dllfrom the publish folder on the server to see errors, verify the Hosting Bundle/runtime version and bitness, the app pool "No Managed Code", file permissions, environment-specific configuration (missing connection string, Key Vault access) and database connectivity at startup.
In short: A kernel-mode HTTP listener used by IIS (and optionally ASP.NET Core directly).
- It accepts connections, parses requests, handles TLS with SChannel, maintains a request queue per application pool, serves cached responses from kernel mode and enforces limits — keeping IIS robust because requests queue in the kernel even while a worker process restarts.
In short: A redirect tells the browser to request a different URL (301/302, address bar changes); a rewrite serves a different resource internally with the URL unchanged.
- For SPAs, add a rewrite rule that sends every request that isn't an existing file, folder or
/api/path to/index.html, so deep links work on refresh; - add MIME types if needed and cache static assets.
In short: Multiple IIS servers behind a load balancer with health checks;
- identical code and config deployed by automation or shared configuration;
- shared machine key / Data Protection keys so cookies and ViewState validate on any node;
- out-of-process session (SQL Server/Redis) or sticky sessions;
- centralised logging;
- shared or replicated file storage for uploads;
- rolling deployments one node at a time.
In short: An application pool with more than one worker process.
- It can help apps limited by per-process locks, but in-process state (session, cache, static variables) isn't shared between the processes, causing inconsistent behaviour.
- Most apps should use one worker per pool and scale out across servers instead.
In short: The application pool is likely stopped: open IIS Manager → Application Pools;
- check Event Viewer System log for WAS errors — rapid-fail protection after repeated crashes, wrong or expired password for a custom identity, missing .NET version, or a crash at startup.
- Fix the cause and start the pool.
- Also check the request queue limit and that the binding/host name is correct.
Enable Windows Authentication (disable Anonymous) on the site, [Authorize] in the app, and either connect to SQL Server with the app pool identity (simplest — grant that account the needed DB permissions and use User.Identity.Name for auditing) or, if SQL must see the end user, configure Kerberos constrained delegation (SPNs for the service account, delegation to the SQL service) and impersonation — more complex, so usually avoided.
In short: The app pool shuts down after the idle timeout (20 min) or recycled overnight, so the first request starts the worker, JITs code and warms caches.
- Set the pool's Start Mode to AlwaysRunning, idle timeout to 0, enable Application Initialization with
preloadEnabledon the site (and a warm-up URL), schedule recycling during low traffic, and consider ReadyToRun publishing to reduce JIT time.