HOWTO: Provision ASP.Net AppDomains and IIS6 Application Pools

This is a frequent source of confusion – how ASP.Net and IIS does application isolation. The key point to remember is that IIS runs native code and thus relies on NT user identity (and thus NT process) for isolation, while ASP.Net runs managed code with CAS and thus can run its own isolation mechanism within a NT process.


I read somewhere that running applications in different pools takes up more memory. My understanding of is that all applications run in their own space under the shared memory space inside w3wp.exe. process.
1. So how is that different from creating seperate pools?
3. Is there a free software to simulate about a 100 connections to a site?
2. Lets say i do run applications in different pools and limit the mem to 10 MB per site, and set it to recycle once limit is reached. Will that be better?

I have a webhosting server with 50 sites and 1 GB ram. (so 50 X 10  = 500 MB) approx

Some of then do take up quite a bit of mem so i can set those up with more space.

Can someone provide me with link or some info on this?

Thank you


I do not understand what you mean by “all applications run in their own space under the shared memory space inside w3wp.exe process” because I think that is where your understanding goes awry. Here is how I view ASP.Net applications and IIS:

  • The basic unit of isolation for an ASP.Net application is its AppDomain. There is exactly one ASP.Net application per AppDomain
  • Every AppDomain identifies and “owns” some portion of the URL namespace. i.e. /ASPX1/WebApp.aspx
  • IIS6 running in Worker Process Isolation Mode partitions the entire URL namespace of the server to be serviced by arbitrary number of Application Pools (minimum of one Application Pool)
  • Application Pool configuration controls the number of NT processes that service the Application Pool (minimum of one w3wp.exe)

Since configuration of Application Pool is arbitrary, it means that it is possible to:

  • Run multiple AppDomains inside of one NT process

    i.e. “/” is serviced by DefaultAppPool, /ASPX1/WebApp.aspx and /ASPX2/WebApp2.aspx are ASP.Net Applications in their own AppDomain, and both AppDomains are sharing the same AppPool and hence same process
  • Run one AppDomain per NT process

    i.e. /ASPX1 is serviced by AppPool1 and /ASPX2 is serviced by AppPool2, /ASPX1/WebApp.aspx and /ASPX2/WebApp2.aspx are ASP.Net Applications in their own AppDomain, so each WebApp is in their own Application Pool and hence their own process
  • It is not possible to run one AppDomain over multiple NT process

In general, it is a poor idea to isolation ASP.Net applications by using Application Pools. Why?

  1. ASP.Net applications all require the .Net Framework, which is a fixed overhead (in the neighborhood of at least 20MB RAM) paid by every process that loads an ASP.Net application. Suppose you have 10 ASP.Net applications. If each application is in its own Application Pool, you can have up to 10 copies of the .Net Framework loaded in memory by each w3wp.exe of each Application Pool. Efficiency says that you really only need one copy of the .Net Framework for all of the ASP.Net applications, and this is possible only if all 10 ASP.Net applications are in the same Application Pool.
  2. ASP.Net applications do not benefit from Application Pool based isolation (by process identity) because ASP.Net runs managed code, which already has CAS and does NOT rely on user identity nor process space for isolation. AppDomain is the logical concept that is enforced by ASP.Net to isolate the ASP.Net applications. Of course, this is a different story for native code applications like ASP, ISAPI, CGI which do benefit from using process space for isolation.

Thus, if you isolation ASP.Net applications using Application Pools, not only are you wasting system RAM resources loading duplicate .Net Framework libraries into memory, you are also gaining no isolation benefits. It is a lose-lose configuration.

For a webhosting server, I recommend creating one Application Pool for use by all ASP.Net applications, and you configure this Application Pool to turn off all health monitoring checks except for private memory limit at 60% physical memory. In particular, you want to turn off periodic recycling and idle timeout, both default values that wreck havoc with ASP.Net because they periodically recycle the worker process and thus causes the subsequent request to re-load the .Net Framework into memory, which takes non-trivial amount of time.

For ASP/CGI/ISAPI based applications, you should still isolate them by Application Pool and use the default IIS6 settings as base guideline, plus any others that you want

As for how to distribute Websites amongst Application Pools, I would first determine the necessary isolation between the websites (ASP.Net applications should share the same application pool while native code applications of different websites should be separated into different application pools), then calculate the memory footprint of each w3wp.exe of each possible Application Pool, and make sure the system can handle that (and have like 256MB remaining buffer for the host OS’s use).

In other words, just blindly isolating websites by creating Application Pools that have unique Application Pool Identites will quickly get you into trouble. Efficient provisioning requires that you analyze what sorts of applications you are running, how the applications need to be isolated by each other, and the representative memory footprint of each application – so that you can make sure it fits within the server’s hardware limits or whatever availability guarantees you are making.


Comments (17)

  1. Robert says:

    Thank you for the detailed explaination David.

    So w3wp.exe is the NT process and each domain’s app runs in its own AppDomain inside w3wp.exe is this correct?

    Something like this


    —- AppDom1 (

    —- AppDom2 (

    My webserver has about 900 domains and each of these have their own aspx apps.

    My server stops serving aspx pages intermittently. When I check the RAM and CPU, I dont see any problems.

    Rebooting the server or ending w3wp.exe from task manager fixes the problem. So at this point is it safe to say that an application within an AppDom is causing this? If so how it it possible, that it affects the other AppDoms?

    What is the purpose of the application pool option in IIS? If not to seperate these applications?

    Sorry for all the questions, I seem to have confused myself with all this.

    Thank you

  2. Two questions –

    1) So what is the effect of web gardening on all of this?

    Obviously we’d have multiple W3WP.EXE’s, each with their own .Net framework loaded. We’d minimize the impact of the "non-trivial amount of time" to load the Framework, since another process would be available to service the request.

    2) For internal sites, we use AppPool Identity as a means of controlling SQL DB access (Our SQL servers only use Windows Integrated Authentication, not SQL authentication). How is this different then using the ASP.NET web.config Indentity Impersonate?

    With App Pool Indentity, the whole w3wp.exe runs as a given user, with web.config Indentity, is it just the AppDomain?

    Thanks! Your blog has got to be one of the most helpful comming out of Microsoft.

  3. David Wang says:

    Robert, Christopher – good questions, and as I started writing the responses I realized that I can better answer each of them as separate blog entries (because there’s lots to explain), so I am going to do that. I will link to them as comments from here when I get done.

    The short answers would be:

    Robert – AppDomain only prevent code from directly affecting each other, but have you isolated all other commonly shared resources (including the fact they share the same w3wp.exe). Application Pools isolate applications by process, not AppDomain, so no direct correlation between the two as far as the logical concept of "isolate these application" is concerned.

    Christopher – Web Garden does not minimize the impact of the "non-trivial amount of time" at all. I will need to explain how Web Gardening works because it is rarely used correctly. As for user identity executing code on IIS, ASP.Net gives the same options as IIS except they are ASP.Net pages-only and configurable via web.config.


  4. One downside of placing all apps in a single shared AppPool is if one web app misbehaves, it can take down the whole AppPool. In a shared webhosting environment, this translates to one bad apple spoiling the bunch. Some bad customer code can impact all other customers in the AppPool. For this reason, I offer two partitioning scenarios: 1) 1:1 Customer:AppPool, or 2) Round-Robin. The 1:1 scenario is the least efficient and least scalable, as you said, but it is the most secure. Round-robin involves distributing customer sites across a fixed number of "shared" AppPools. While high density of customers per server is ideal for profits, it is less than ideal for the customer experience. Further, being able to identify one misbehaving web app in an AppPool of hundreds or thousands of other websites is akin to finding a needle in a haystack.


    – Mark

  5. kfarmer says:

    Actually, there is a specific reason *to* use application pools, if you have several different web apps as well as a database, and the requirements are that 1) database passwords are not stored in config, 2) not hardcoded, either, and 3) each app has a seperate password.

    In my experience, this means that you use windows authentication, and that the application pool’s security account be set per pool. Actually, I can see this being a pattern for any sort of per-app security, where part of the security is outside of the CLR’s control.

  6. David Wang says:

    Mark – Yup, we deliberately left the options open-ended for shared webhosting owners to determine what strategy works best for their price/availability usage scenario. That is a part of your profit model, after all…

    What the IIS6 team did for reliability testing (simulated user activity/request load), we assumed an ISP has these categories:

    1. Dedicated hosting – customer has own AppPool, dedicated support

    2. Shared hosting – customer shares AppPool with 1-5 other customers, high-touch support

    3. Mass hosting – everyone in the same AppPool, low-touch support

    If one bad apple spoils the bunch in #3, that is opportunity to up-sell #2 – you get what you paid for. With #2, these are you good customers, so they are more isolated and you can troubleshoot easier. Round-Robin amongst several fixed Application Pools can also work.

    Of course, finding the bad WebApp can be hard, but tools like DebugDiag should make it easier to identify the exact web page that is spinning the CPU in a process or hanging on a lock as well as which code module is crashing.

    Personally, I would try to simultaneously max out the amount of RAM and # of processes supported by your given hardware (assuming CPU/Network/Disk are not the bottleneck). It gives you the most app isolation per MB of RAM and is a reasonable approximation to reliability.


  7. David Wang says:

    kfarmer – actually, I would rephrase your reason as:

    "If your application takes advantage of Application Pool properties, such as process identity, healths-monitoring metrics, etc, then it makes sense to isolate them by Application Pool."

    In your case, you are probably hard coding username/password in IIS Application Pool configuration, and then you run ASP.Net application with impersonate="false" so that ASP.Net code uses the process identity to perform actions while you can still use Windows authentication to authenticate the users.

    Another alternative could be to hard code the username/password in IIS Anonymous User account at a per-App level, and then you run ASP.Net application with impersonate="true" so that ASP.Net uses the impersonated identity to perform actions while you can still use ASP.NET Forms authentication (enable only Anonymous authentication in IIS) to authenticate the user.

    The latter scenario would NOT need an Application Pool for isolation nor user credentials (because anonymous user account is isolating it for ASP.Net at a per-App scope).


  8. David – you said "reliability testing (simulated user activity/request load)"

    What tools did your team use to simulate this load? What was the testing methodology?

    We would like to find our "sweet spot" in terms of isolation vs. density



  9. robert says:

    Thank you Mark and David,

    Thats exactly what i was looking for. Yes my servers host a lot of sites and sometimes one bad app causes other aspx apps to stop resonding. And this is why i seperated sites, that i suspected, into a different pool. I have informed the customers with the bad app to do something about their code.

    Thank you again for all the info really helped a lot.

  10. David Wang says:

    Mark – we actually custom built a test application and load simulation tool because we would dynamically exercise the test application and no tool contained the necessary state management which would not end up being a custom script anyways – so we just cut the hassle of the tool out of the picture.

    We really did not worry about measuring a "sweet spot" since we wanted to measure reliability in terms of detectable downtime – so we just cranked up enough client machines to keep the server busy at some predefined threshold and let the simulation vary over time.


  11. Dave M. says:

    Dave; first of all, great article.

    We are currently in the mist of migrating off of IIS 5 onto IIS 6 and are going design pains as to how best carve up application pools.

    In the IIS 5 word we have run everything high isolated due to the fact that application don’t seem to get along, but at the expense of system resources such as memory and desktop heap.

    Now or application are currently a mix of classic ASP and .net, with a mixture of old and new even within the same application.

    We mostly use a portal design that breaks down to around twelve sites per server, which upwards of fifty plus virtuals under each site.

    Now, the dilemma, do we run everything (site and virtual) in their our pool? What about resources, maybe classic ASP today, and .NET tomorrow, think of the resources.

    So I was thinking of the following and looking for comments:

    Run each web site it it’s own application pool.

    Each virtual directory under a site will run in the site’s application pool.

    Once fully .NET, move to a .NET pool (per. your article)

    This method of implementing application pools brings us to middle ground. i.e. more than a single application pool that would be limiting, yet simpler than an application pool for every site and virtual directory which could be overwhelming.


  12. David Wang says:

    Dave – Your approach seems fine to me. You are basically running around 12 Application Pools per server, each of them possibly loading its copy of .Net Framework libraries, and after you multiply them if you Web Garden (which I’m presuming you don’t… unless you have good reason [that’s the topic of a future blog entry — when to/not Web Garden]), you should multiply the expected resource consumption of RAM, CPU, Disk, Network Bandwidth of each website in "aggregate" after loading both ASP/ASP.Net apps and make sure that fits inside the physical hardware of your server.

    Most of the time, it is RAM and CPU that are the biggest worry, so do some quick math to check. And ASP.Net memory footprint usually dwarfs the ASP footprint (unless you are running custom COM components that chew up their own memory resources either in-proc of w3wp.exe as Library apps or OOP hosted in individual dllhost.exes). Ballpark calculations are reasonable… I know of some MS OPS teams that basically do their calculation and then double it and round up to nearest power of 2 to ensure their hardware meets guestimated peak capacity.


  13. David Wang says:

    Dave – And regarding your followup –

    You can treat ASP.Net applications like ASP applications except each has greater RAM/CPU resource requirements and isolate appropriately.

    Realistically, this just means that given comparable HW and Application Isolation requirements, you end up with less dense ASP.Net application deployments than ASP.

    There is no magic to allow apps to share common resources for efficiency yet not have bad apps bring down good apps using the same resources.


  14. Stormy says:

    The whole purpose of Application Pooling and process identity is not to just manage resources (or mismanage, as is supposed here) but really to control security. In theory, you WANT to use App Pooling so that a devious user doesnt setup an account or web app that takes down a server, then turns around and takes control of it. Thats why identities in separate pools are beneficial. Its all about security. If thats at expense of resources, then buy a bigger server! – stormy

  15. Jacob Webber says:

    I have to agree with stormy 100%. Especially for being a web host, security should be #1 over ram anyday.

  16. DavydCarr says:

    Wow.  I just read through this thread and a couple of related ones and I can only say I wish I would have found this resource years ago.  Amazing, simply amazing.

    Of course what brought me here is my problem… at least I think I have a problem.  Hopefully I can explain it well enough.

    We have several apps running on IIS 6.  We use application pools, mostly on a per app basis.  I noticed a couple months back that one of our apps appeared to have stopped using it’s configured pool.  How I realized it was twofold – one, there was a performance issue.  Two, the user name when monitoring activity was no longer the app pool identity; it had reverted to the login ID (UID).  I found that a developer had accidentally moved a web.config file that had pooling set to false.  Problem solved.

    Several months later, after other performace issues had surfaced and some of our apps were moved to different servers to distribute the load, I am seeing this same indication – the apps are showing up with the UID instead of the pool identity which leads me to believe the pool is not being utilized.  However, I am at a loss to determine why (or if the symptom is truly indicative of the pool not being used).

    I have gleaned a couple of things from this thread and the other pool threads (different frameworks using the same pool, but I don’t think that is the issue here, as currently it is pretty much one app per pool).

    So I ask, is the symptom (seeing the UID rather than the pool identity) really indicating a problem and if so, what are the things that would cause what appears to be a correctly configured app pool from being used.  We’ve recreated them with the same result.

    Thanks to everyone in advance, and special thanks to David for putting so much into this resource.



  17. DavydCarr says:

    After much wrangling, it was discovered that we have set up the identity on each of the machines (I guess as a method to allow pooling to work without domain level security… ?) and at least one of those identities did not have the same password as the others.

    It fixed the issue.