In a Nut Shell: Shared Hosting Improvements on IIS7

We were meeting with AdHost today and I gave a quick 30-minute spiel on what we improved in IIS7 when it comes to Shared Hosting. Here is the list (not necessarily complete):

1) Shared Configuration

You can have the central IIS configuration file (applicationhost.config - the metabase is gone) on a central server and share it across multiple front ends. Not limited to Shared Hosting, but most Hosters love it. More info:

2) Delegated Configuration

IIS configuration can be stored either centrally like in IIS 6.0 or a hoster can allow a customer to configure his own settings. No need to call up the hoster if default documents or authentication settings need to be changed. These settings can be delegated on a feature by feature basis or even on a per configuration property level. Delegated configuration settings are shared with ASP.NET in web.config files. More information:

3) New Publishing Stack

IIS7 offers a brand-new publishing stack, i.e. FTP7 supporting SSL, WebDAV (map a drive in Explorer to connect to your web-site) and a new version of Frontpage Server Extensions.

More information:

Frontpage Server Extensions:

4) Improved PHP Support

Wordpress, Drupal, phpBB are very popular and there are tons of other pre-packaged PHP applications out there. But PHP didn't run to well on the Windows platform. This changed with the FastCGI feature that was introduced for IIS 6.0 and 7.0. FastCGI is shipped as part of IIS in Windows Server 2008.


And something else. The SQL Server drivers for PHP were slowing things down quite a bit. But not anymore. There is new PHP driver available written by the SQL Server team itself:

5) Using Windows System Resource Manager for CPU Throttling

We are currently working on a new article that outlines how to use CPU Throttling for IIS Application Pools. WSRM allows a Hoster to make sure that no Application Pool monopolizes the CPU(s) of a particular machine. Here is a start:

6) Directory Quota Support

Windows Server 2008 comes with a set of new file system features; one of them is the "File System Resource Manager" (FSRM) which supports directory quotas. With FSRM a Hoster can make sure the size of a directory doesn't get bigger than a configured limit. Soft limits generate an Eventlog entry or send e-mail, hard limits don't allow the files to be written at all. File Screens can ensure that certain file types and patterns are not uploaded. Hosters can also define individual templates that apply these settings in an uniform way. Directory quotas can be set via UI, via command-line tools or via scripting. More information:

Configuration Example (only PowerShell for now):

param (    [string]$directory, 
    [int] $quotaLimit,
    [int] $threshold

$qMgr = new-object -com Fsrm.FsrmQuotaManager;
$quota = $qMgr.CreateQuota("$directory");
#quota in MB
$quota.QuotaLimit = ($quotaLimit*1024*1024);
#write to eventlog when $threshold is exceeded
$action = $quota.CreateThresholdAction($threshold, 1);
$action.EventType = 1;
$action.MessageText = "Disk quota ($quotaLimit MB) for directory $directory exceeded.";

7) Bandwidth Throttling

Media content like videos or audio files (e.g. Podcasts) become more and more pervasive in Hosted Environments. But Media content can become quite a problem. Usually Hosters want to provide fast download times to maximize the user experience. This is not the case with media content however and here is why:

If you look at the grand scheme of things only a fraction (about 20%) of media content is consumed before the user browses to something else. Just ask yourself how many youtube videos you really watch from start to finish.

If you have a fast connection 100% of the media file gets downloaded until the user stops watching. 80% of the bits transferred were wasted. That's not a problem if you have unlimited bandwidth, but who has that? The IIS7 Bitrate Throttling Module allows Hosters to progressively throttle the bandwidth of media and other content to a desired rate or to the rate that is encoded in the media file itself. More information:

8) IIS7 Core Web Server Improvements

a) No need for an anonymous account anymore.

Whenever requests are not authenticated IIS uses an anonymous user account to access web content. In IIS6 a default account is created named "IUSR_<machinename>. For isolation purposes Hosters usually create one anonymous user account for each web-site.

You don't have to do that anymore in IIS7. By leaving the anonymous username and password empty IIS7 Application Pools will use the Application Pool identity itself to access anonymous content. So if a Hoster has an individual Application Pool account for each customer he doesn't have to create a second anonymous account on top of that. The single Application Pool account is enough.

Configuration Example (removes the anonymous user server-wide):

windir%\system32\inetsrv\appcmd set config -section:anonymousAuthentication 
-username:"" -password:""

User Interface


b) dynamicIdleThreshold

In most Shared Hosting environments very active (hot) sites live together with infrequently requested (cold) sites. When too many Application Pools for these sites get spawned up memory becomes sparse and the Windows Memory Manager starts moving infrequently used memory pages to the pagefile. If memory pressure gets too high memory is over-committed and the machine starts thrashing. In this case the system excessively swaps memory pages between RAM and pagefile because more and more of the required memory pages reside in the page file and need to be paged back into memory. Excessive swapping of memory pages is also called thrashing. It usually starts happening when about 130% of the memory is committed. Example: For a machine with 2GB physical RAM thrashing might start at 2.6GB (2GB RAM + 600MB in the pagefile = 2.6GB/2.0GB = 130%).

Thrashing is not fatal, but it certainly slows down the system. Requests start to take longer than usual. The worse thrashing gets the longer responses will take.

Now back to IIS: there is a remedy in IIS 7.0 when memory becomes sparse. It's called dynamicIdleThreshold. All you have to do is to configure the percentage of memory committed, e.g. 130. Should the system get close to this limit IIS will start reducing the idle timeout of Application Pools. IIS7 starts

  • At 80% of the dynamicIdleThreshold setting it reduces the idle timeout of all Application Pools by half, e.g. the 20 minute default timeout would be set to 10 minutes.
  • At 85% of the dynamicIdleThreshold setting it reduces the idle timeout of all Application Pools to 1/4th, the 20 minute default timeout would be set to 5 minutes.
  • At 90% of the dynamicIdleThreshold setting it reduces the idle timeout of all Application Pools to 1/8th, i.e. 2.5 minutes if you use the 20 minute default.
  • At 95% of the dynamicIdleThreshold setting it reduces the idle timeout of all Application Pools to 1/16th, i.e. 1 minutes if you use the 20 minute default.
  • At 100% of the dynamicIdleThreshold setting it reduces the idle timeout of all Application Pools to 1/32th, i.e. 1 minutes if you use the 20 minute default (one minute is the minimum).

For math wizards: Let's suppose we set dynamicIdleThreshold to 130 on our machine with 2GB physical RAM. The 80% threshold would be reached if 2.08GB of the memory are committed (80% of 2.6GB (130% dynamicIdleThreshold)).

As a net result cold Application Pools get timed out much faster while hot Application Pools don't get timed out because they continuously receive requests and their idle timeout counter gets reset constantly. An Eventlog entry is generated every time an Application Pool is timed-out due to a reduced time-out. In our test environment we can host up to 10 times more Application Pools when enabling the dynamicIdleTimeout setting.

The side effect of this setting is of course that process data like in memory session state gets deleted if an Application Pool times out.

Here is how you configure the dynamicIdleThreshold setting:

%windir%\system32\inetsrv\appcmd set config 
-section:system.applicationHost/webLimits -dynamicIdleThreshold:130

c) Static and Dynamic Compression

Compressing responses can be a big benefit for HTTP clients which have limited bandwidth, for example cell phones or dial-up connections. It can also save a lot of bandwidth.

IIS automatically compresses static content like html or text files. To do this the HTTP client has to send the "Accept-Encoding: gzip" header. Most HTTP clients like Internet Explorer or FireFox do this automatically. The big advantage with static compression is that IIS can cache the compressed representation of the content in memory and even on disk. For the next response the already compressed representation of the content gets sent. This way it doesn't have to recompress for every new request. Compressing most static content is the default for IIS7.

Dynamic content (e.g. ASP.NET, PHP or other Web Application Frameworks) is a bit trickier because the compression has to be done for every response and that costs CPU cycles of course. Due to the benefits described above it might be a good idea to turn dynamic compression on if spare CPU cycles are available however. This is not an all-or-nothing either because IIS7 has some high-watermark - low-watermark settings that allow to disable compression if the CPU reaches a certain limit, e.g. 90%.

Configuration Examples:

Enable Dynamic Compression

%windir%\system32\inetsrv\appcmd.exe set config "Default Web Site" 
-section:system.webServer/urlCompression /doDynamicCompression:"True"

Set Dynamic Compression High Watermark

%windir%\system32\inetsrv\appcmd.exe set config  
-section:system.webServer/httpCompression /dynamicCompressionDisableCpuUsage:"80"

d) Application Pool SIDs

IIS7 generates a unique Security Identifier (SID) for every Application Pool it starts. This allows to isolate content for two or more Application Pools even if they run as the same account. You can ACL resources like files and directories for these individual Application Pool identities. See Ken Schaefer's blog for more details:

Configuration Example:

icacls C:\content\site1\test.txt /grant "IIS APPPOOL\Site1AppPool":R

e) Failed Request Tracing

Troubleshooting Web Server errors is hard. Especially in Hosting Environments where customers write the code but the Hoster has to troubleshoot. Often times there is a lot of code that gets executed before a response is returned. And a request can fail anywhere in the request processing. Failed Request Tracing allows an IIS administrator to specify rules for failed requests. If a request conforms to the rule (e.g. request takes longer than 30 seconds) IIS will write a detailed trace of the "failed" request to disk. Here is an example of the output:


More information on Failed Request Tracing:

f) Running Wow64

RAM is cheap and having machines with more than 4GB of RAM is not outrageous anymore. To address more than 4GB of RAM a 64-Bit Operating System is necessary. Windows Server 2008/64-Bit is thoroughly tested and I would recommend running on 64 instead of 32-Bit. Compatibility is important however and IIS software like PHP or ISAPI filters and extension are not be available as 64-Bit binaries. 32-Bit is also quite a bit lighter-weight and doesn't need as much memory. The solution: install the 64-Bit version of Windows Server 2008 but run 32-Bit Application Pools. The "enable32BitAppOnWin64" is a per Application Pool setting, i.e. 32-Bit and 64-Bit Application Pools can be run side-by-side.

Configuration Example:

appcmd apppool set / /enable32BitAppOnWin64:true

User Interface



There are a ton of new features in Windows Server 2008 and IIS7 that make Shared Hosting easier. I tried to outline the most important ones but I probably forgot a bunch. Stay tuned for future updates. 

No Comments