Search

IIS Workflow Described

1 views

The Anatomy of an IIS Request Pipeline

When a browser sends a URL, the journey starts far below the address bar. A TCP handshake links the client to the server, and the first packet arrives at the HTTP.SYS driver, a kernel‑mode component that owns the HTTP stack on Windows. HTTP.SYS examines the request line, validates the method and headers, and checks the URL against the IIS configuration. If the request looks legitimate, the driver hands it over to the worker process, usually w3wp.exe, which runs inside an application pool.

Application pools provide isolation. Each pool owns its own set of worker processes and applies settings such as memory limits, recycling intervals, and authentication mode. A crash in one site never takes down the whole machine because the offending process lives in its own pool. If you need to share resources between sites, you can run them in the same pool, but that exposes them to each other’s faults.

Once the request reaches the worker process, IIS activates a series of modules that form the request pipeline. The first set is the request filtering module. It applies rules defined in web.config or the global IIS configuration to block malicious patterns, enforce URL length limits, and reject disallowed verbs. A typical rule might block the X-Requested-With header, which could interfere with AJAX frameworks, or trim overly long query strings that could indicate a brute‑force attack.

If the request passes filtering, it enters the core pipeline where authentication and authorization modules take the helm. Forms Authentication checks for a cookie; if absent, it issues a 302 redirect to the login page. Windows Authentication validates the Kerberos or NTLM ticket, while OAuth modules can hand off to external providers. After authentication, the Authorization module consults web.config to ensure the authenticated identity has the right role or group membership. When any module fails, it can terminate the pipeline early by sending a 401, 403, or 404 response.

A successful request reaches the handler mapping stage next. Here IIS looks at the URL and HTTP verb to pick a handler. Static files are served by the StaticFile handler, which streams the file contents directly to the output stream. Dynamic requests, such as those that hit an ASP.NET MVC controller, are routed to the MvcHandler or a custom ISAPI/ASP.NET handler. The chosen handler may load the .NET CLR, JIT‑compile the assembly, and invoke the application’s entry point. While the CLR is warming up, IIS queues the request and the worker process stays busy with other jobs.

Handlers can hook into the lifecycle by implementing event handlers like BeginRequest, EndRequest, and Error. This gives developers the ability to inject logging, modify headers, or perform cleanup. After the handler finishes, the response body and headers travel back up the pipeline. Compression modules examine the Accept-Encoding header to decide whether to gzip or deflate the body, adjusting Content-Encoding accordingly. Caching modules then check for conditional GET requests; if the client already holds a fresh copy, IIS can answer with a 304 Not Modified, saving CPU cycles.

Once the response is ready, HTTP.SYS takes the serialized packet and writes it to the network socket. If the request included a Keep‑Alive header, the TCP connection stays open for a short period, allowing subsequent requests to reuse the same socket. Without Keep‑Alive, the server tears down the socket after sending the response. This end‑to‑end flow normally completes in milliseconds on modern hardware, but each hop presents a place to tune performance, add diagnostics, or block unwanted traffic.

Configuring and Customizing the Workflow

The first line of defense for a web application is the web.config file, a hierarchical XML document that can be placed in any application root. Settings in a lower‑level file inherit from higher levels unless overridden, so you can set a global Request Filtering rule at the server level and then relax it for a specific site.

Modules live under the system.webServer/modules section. Adding a custom module is as easy as dropping a line: <add name="DbLogger" type="Company.Logging.DbLoggerModule, Company.Logging" />. The module class receives callbacks for request events, allowing it to log every request to a database without touching application code. Modules execute in the order they appear, but you can tweak the order using the preCondition attribute or by rearranging XML elements. A typical best practice is to place authentication modules first, followed by custom logging, and then any security modules that may block unauthenticated traffic.

Handler mappings sit in system.webServer/handlers. You can map a URL pattern to a handler class or to a built‑in handler. For instance, to route all URLs ending in .mvc to a custom MVC handler, you would add an entry like <add name="MvcHandler" path=".mvc" verb="" type="Company.Mvc.MvcHandler, Company.Mvc" preCondition="integratedMode" />. Removing the StaticFile handler for a specific directory prevents accidental exposure of source files such as .cs or .config when the directory is mistakenly made public.

Beyond modules and handlers, IIS offers event hooks that let you run code at defined points. The system.webServer/aspNetCore section is commonly used to host ASP.NET Core behind IIS. It accepts parameters such as startupTimeLimit to give the Core process time to spin up, or environmentVariables to inject variables into the application environment. When you need to capture detailed diagnostics, enable traceFailedRequestsTracing; the resulting XML traces include the module that threw the exception and the stack trace, making it easier to pinpoint configuration errors.

Performance tuning is a blend of configuration and code changes. In system.webServer/security/requestFiltering, you can limit the request body size, block verbs like DELETE, or reject known attack patterns such as ../ sequences. The system.webServer/caching section allows you to set a default cache duration for static files or to enable Output Caching on specific paths. For example, <add fileExtension=".js" duration="86400" variation="UserAgent" location="Server" /> tells IIS to cache JavaScript files for a full day, varying the cache by User Agent to keep mobile and desktop versions separate.

When you couple IIS caching with a content delivery network, global latency drops noticeably. The CDN serves cached assets from a location close to the client, while IIS handles dynamic requests. This division keeps the worker processes light and reduces the likelihood of timeouts during peak traffic.

Common Pitfalls and Performance Tuning in IIS Workflows

Application pool settings are a frequent source of trouble. Running a pool in InProcess mode shares the same w3wp.exe with other sites, so a memory leak in one application can bring down all sites in that pool. Switching to OutOfProcess mode isolates the application, but the added inter‑process communication can cost a few milliseconds per request. The decision hinges on the site’s memory footprint and the number of concurrent sites on the server.

Request filtering rules can unintentionally block legitimate traffic. A rule that rejects the X-Requested-With header can break modern single‑page applications that rely on AJAX. Overly strict URL length limits may truncate long query strings used by APIs that embed JSON or XML payloads. Test every filtering rule in a staging environment before promoting it to production, and keep a backup of the default configuration so you can roll back quickly.

Large file uploads often fail because the default maxAllowedContentLength is set to 30 MB. Raising that value to 104857600 (100 MB) in requestFiltering solves the problem. Likewise, the maxRequestBytes setting controls the maximum size of the entire request, including headers. Adjusting both ensures that legitimate uploads aren't rejected while still protecting against oversized requests.

Output Caching is a double‑edged sword. If you cache a dynamic page that changes frequently and forget to set the Cache-Control header, clients may receive stale data. The Cache-Control: no-store directive forces the browser to revalidate with the server. Tools like the IIS Request Monitor can surface which modules consume the most CPU time. If the ASP.NET Runtime module dominates, consider scaling the worker processes or reviewing the application for inefficient database queries or blocking calls.

Monitoring is vital. The IIS Manager exposes Performance Monitor counters such as Requests/Sec and Process Queue Length. Setting alerts on these counters lets you catch spikes before they affect users. The logFile section writes detailed HTTP logs; combined with a log parser like Log Parser Studio, you can spot failed requests, slow responses, or blocked URLs. Historical analysis of these logs often reveals patterns that simple monitoring misses, such as a gradual increase in 403 errors tied to a misconfigured rule.

To keep a workflow healthy, maintain a cycle of observation, diagnosis, and tuning. Review the event log for recurring errors, experiment with smaller memory limits in application pools, and audit the module order whenever you add a new authentication or logging module. By staying mindful of how each component interacts within the pipeline, you can keep applications responsive, secure, and resilient without chasing after every single configuration detail.

Suggest a Correction

Found an error or have a suggestion? Let us know and we'll review it.

Share this article

Comments (0)

Please sign in to leave a comment.

No comments yet. Be the first to comment!

Related Articles