To fully understand the problem and the partial solution we found, I'll review how an application in IIS and the .NET CLR is logically structured.
Global Assembly Cache (GAC)
The GAC is a cache of Common Language Infrastructure assemblies available be shared by multiple applications. Assemblies loaded from the GAC are loaded with Full Trust, note that in .NET 4 Code Access Security (CAS) has changed significantly and permissions are determined largely by the permissions of the executing account.
Application Pools
Application Pools (App Pools) are grouped sets of Web Applications under IIS that share the same W3WP worker process. Each application in an app pool runs under the same service account and as a result with the same account permissions. Application pools can be viewed as a mechanism for creating isolation between applications in IIS. Often sys admins create a separate application pool for each web application. Generally you'll have a single worker process for an application in IIS though you can configure multiple; this is refereed to as a Web Garden. Just a Note: Generally you want to avoid Web Gardens as they can create all sorts of problems for you. Their purpose is intended to be supporting long running requests without creating a blocking situation for your application.
Thread
Within a worker process, one or more threads, configurable in IIS, are available. Threads are like the workers on an assembly line with App Domains being the different stations for a worker to do their work. A thread does all the work inside of an application and they can only work on one App Domain at any given time. A thread can however work for multiple domains over the life cycle of the application bouncing back and forth between as work needs to be done.
AppDomain
An application domain is a unit of isolation within the .NET framework. Every application can have one or more application domains. By default, every application has 1 AppDomain however you can create AppDomains within your code to manage assembly dependencies. Within an AppDomain, there are three contexts for assemblies that are loaded within that domain. These contexts are a further isolation unit within an AppDomain into which assemblies are loaded based on the method of loading.
![]() |
Logical Runtime Structure of IIS Hosted Websites |
The GAC is a cache of Common Language Infrastructure assemblies available be shared by multiple applications. Assemblies loaded from the GAC are loaded with Full Trust, note that in .NET 4 Code Access Security (CAS) has changed significantly and permissions are determined largely by the permissions of the executing account.
Application Pools
Application Pools (App Pools) are grouped sets of Web Applications under IIS that share the same W3WP worker process. Each application in an app pool runs under the same service account and as a result with the same account permissions. Application pools can be viewed as a mechanism for creating isolation between applications in IIS. Often sys admins create a separate application pool for each web application. Generally you'll have a single worker process for an application in IIS though you can configure multiple; this is refereed to as a Web Garden. Just a Note: Generally you want to avoid Web Gardens as they can create all sorts of problems for you. Their purpose is intended to be supporting long running requests without creating a blocking situation for your application.
Thread
Within a worker process, one or more threads, configurable in IIS, are available. Threads are like the workers on an assembly line with App Domains being the different stations for a worker to do their work. A thread does all the work inside of an application and they can only work on one App Domain at any given time. A thread can however work for multiple domains over the life cycle of the application bouncing back and forth between as work needs to be done.
AppDomain
An application domain is a unit of isolation within the .NET framework. Every application can have one or more application domains. By default, every application has 1 AppDomain however you can create AppDomains within your code to manage assembly dependencies. Within an AppDomain, there are three contexts for assemblies that are loaded within that domain. These contexts are a further isolation unit within an AppDomain into which assemblies are loaded based on the method of loading.
- default-load context
- Assemblies resolved by the CLR from the Global Assembly Cache (GAC) or the private application bin.
- load-from
- Assemblies loaded from an application's code using the Assembly.LoadFrom method.
- reflection-only
- Assemblies loaded only for reflection.