Best practices for creating websites in IIS 6.0

Every time I create an IIS website, I do some steps, which I
consider as best practice for creating any IIS website for better
performance, maintainability, and scalability. Here’ re the things
I do:

Create a separate application pool for each web
application

I always create separate app pool for each web app because I can
select different schedule for app pool recycle. Some heavy traffic
websites have long recycle schedule where low traffic websites have
short recycle schedule to save memory. Moreover, I can choose
different number of processes served by the app pool. Applications
that are made for web garden mode can benefit from multiple process
where applications that use in-process session, in memory cache
needs to have single process serving the app pool. Hosting all my
application under the DefaultAppPool does not give me the
flexibility to control these per site.

The more app pool you create, the more ASP.NET threads you make
available to your application. Each w3wp.exe has it’s own
thread pool. So, if some application is congesting particular
w3wp.exe process, other applications can run happily on
their separate w3wp.exe instance, running under separate app
pool. Each app pool hosts its own w3wp.exe instance.

So, my rule of thumb: Always create new app pool for new web
applications and name the app pool based on the site’s domain name
or some internal name that makes sense. For example, if you are
creating a new website alzabir.com, name the app pool alzabir.com
to easily identify it.

Another best practice: Disable the DefaultAppPool so that
you don’t mistakenly keep adding sites to
DefaultAppPool.

"/wp-content/images/7996065FE95A429CA2023FA56BD02AF2.png">
"border-top-width:0px;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;"
height="340" alt="image" src=
"/wp-content/images/069AB78FB9E6BAFC374589918C8661C3.png"
width="664" border="0">

First you create a new application pool. Then you create a new
Website or Virtual Directory, go to Properties -> Home Directory
tab -> Select the new app pool.

"/wp-content/images/610BF76709BBFCE249DEBBB99424503F.png">
"border-top-width:0px;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;"
height="501" alt="image" src=
"/wp-content/images/7B0921F0015498D6B08C4F8112B66677.png"
width="620" border="0">

Customize Website properties for performance,
scalability and maintainability

First you map the right host headers to your website. In order
to do this, go to WebSite tab and click on “Advanced” button. Add
mapping for both domain.com and "http://www.domain.com">www.domain.com. Most of the time,
people forget to map the domain.com. Thus many visitors skip typing
the www prefix and get no page served.

"/wp-content/images/B43328B85DE5FEB41E70D5C22B3264BF.png">
"border-top-width:0px;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;"
height="493" alt="image" src=
"/wp-content/images/70F6F684C0721FE00FF0CACC60B93D7F.png"
width="648" border="0">

Next turn on some log entries:

"/wp-content/images/32D92CD9A6A8D8C1E6495BD26D95AEC0.png">
"border-top-width:0px;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;"
height="458" alt="image" src=
"/wp-content/images/F8161A8F125A01A74E3011ED0337F1CB.png"
width="605" border="0">

These are very handy for analysis. If you want to measure your
bandwidth consumption for specific sites, you need the Bytes Sent.
If you want to measure the execution time of different pages and
find out the slow running pages, you need Time Taken. If you want
to measure unique and returning visitors, you need the Cookie. If
you need to know who is sending you most traffic – search engines
or some websites, you need the Referer. Once these entries are
turned on, you can use variety of Log Analysis tools to do the
analysis. For example, "http://awstats.sourceforge.net/">open source AWStats.

But if you are using Google Analytics or something else, you
should have these turned off, especially the Cookie and Referer
because they take quite some space on the log. If you are using
ASP.NET Forms Authentication, the gigantic cookie coming with every
request will produce gigabytes of logs per week if you have a
medium traffic website.

"/wp-content/images/0E4F1C151A53CD8E3BEAD8419266FEB6.png">
"border-top-width:0px;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;"
height="269" alt="image" src=
"/wp-content/images/CF4EB23719BEB9693CFE6D5A5BF30D55.png"
width="473" border="0">

This is kinda no brainer. I add Default.aspx as the default
content page so that, when visitors hit the site without any .aspx
page name, e.g. alzabir.com, they get the default.aspx served.

"/wp-content/images/3F39D218FE37C7E96027E4819449063C.png">
"border-top-width:0px;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;"
height="461" alt="image" src=
"/wp-content/images/DB3FD8C9C6EDFBAF1918E8D770CD4394.png"
width="475" border="0">

Things I do here:

  • Turn on Content Expiration. This makes static files remain in
    browser cache for 30 days and browser serves the files from its own
    cache instead of hitting the server. As a result, when your users
    revisit, they don’t download all the static files like images,
    javascripts, css files again and again. This one setting
    significantly improves your site’s performance.
  • Remove the X-Powered-By: ASP.NET header. You really
    don’t need it unless you want to attach Visual Studio Remote
    Debugger to your IIS. Otherwise, it’s just sending 21 bytes on
    every response.
  • Add “From” header and set the server name. I do this on each
    webserver and specify different names on each box. It’s handy to
    see from which servers requests are being served. When you are
    trying to troubleshoot load balancing issues, it comes handy to see
    if a particular server is sending requests.

"/wp-content/images/93F6098366F78637379016D2253E72C3.png">
"border-top-width:0px;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;"
height="465" alt="image" src=
"/wp-content/images/81F068768E8F31D7511D452863089388.png"
width="538" border="0">

I set the 404 handler to some ASPX so that I can show some
custom error message. There’s a 404.aspx which shows some nice
friendly message and suggests some other pages that user can visit.
However, another reason to use this custom mapping is to serve
extensionless URL from IIS. "http://msmvps.com/blogs/omar/archive/2007/04/29/serve-extensionless-url-from-asp-net-without-using-isapi-module-or-iis-6-wildcard-mapping.aspx">
Read this blog post for details
.

"/wp-content/images/B296D17694A936AF1C9D582587215893.png">
"border-top-width:0px;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;"
height="459" alt="image" src=
"/wp-content/images/0BB0C3F2F1FF155CF6A7802B136EF2DC.png"
width="471" border="0">

Make sure to set ASP.NET 2.0 for your ASP.NET 2.0, 3.0 and 3.5
websites.

Finally, you must, I repeat you “MUST” "http://msmvps.com/blogs/omar/archive/2006/08/10/iis-6-compression-quickest-and-effective-way-to-do-it-for-asp-net-compression.aspx">
turn on IIS 6.0 gzip compression
. This turns on the Volkswagen
V8 engine that is built into IIS to make your site screaming
fast.

"scid:B3E14793-948F-49af-A347-D19C374A7C4F:c9260f79-7b63-4c02-96a4-1a4a412a5a65"
style=
"padding-right:0px;display:inline;padding-left:0px;padding-bottom:0px;margin:0px;padding-top:0px;">

"http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fmsmvps.com%2fblogs%2fomar%2farchive%2f2008%2f10%2f04%2fbest-practices-for-creating-websites-in-iis-6-0.aspx">kick it on DotNetKicks.com src=
"http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fmsmvps.com%2fblogs%2fomar%2farchive%2f2008%2f10%2f04%2fbest-practices-for-creating-websites-in-iis-6-0.aspx"
border="0">

25 Comments

  1. this is a very nicely build checklist for starters and they will find it quite handy at times to come.

    thanks.

  2. I think that enabling content expiration without explanation may be dangerous for thouse who don't know about client-caching.

  3. Great step by step guide! I follow exactly the same steps except i also disable the logging feature as i use Google Analytics for my stats.

    To streamline the process, I normally create a new website from file with all the preset settings.

    Cheers

    Caleb Tan

    http://calebtan.com

  4. Very useful guide. Thanks.

    Do you have any recommendation for the 'Identity' property for the App Pool?

    Do you create a new user for each Pool/site?

    What about the Authentication method?

    Thanks in advanced

  5. When we define Session Null check conditionin Master Page cs file, it does not work for main aspx page load and we receive exceptions if session specific information is tried for retrieval; I was under the impression that Master page session null condition will take care of proper data generation; but it does not happen and we need to manage the session Null condition in Main Page as well, which is some times a PAIN.

    Regards

    RS

    http://www.healthsprint.com/

  6. Hi,

    Are you sure about the new application pool for each new application? wont it increase the memory requirement?

  7. It is a very nice article. I never followed these steps in my office. But now definitely I'll follow all these. Thanx a lot

  8. This is really cool..thanks.

    Just curious, why should i turn of the “Index this resource” property?

  9. Very good, thank you. I also would like to know why turn off 'Index this resource'? thanks.

  10. Hi,

    Excellent Information, Just one question, Can i create a new application pool and set the new pool for an existing web site?

    Thanx

  11. This is really good stuff and better performance with these changes to hosting a site

  12. Hey Omar

    Superb cheklist with several issues I hadn't thought of, but for sure will incorporate in future site setups.

    About the default content page I think I read somewhere a long time ago (maybe in the MS Press “Developing web applications” book for the 70-315 exam) that you should put Default.aspx in top of the list to save some search time.

    Whether this is true or not I have this in my website creation practice. I add default.aspx, moves it to the top and delete default.asp and index.htm and also default.htm if I don't use the VS publishing feature (that feature puts a default.htm with a maintenance message on while files are being published).

    Thanks for sharing :-)

  13. Hi

    I have the web load balancing and followed

    you document on HHTP header by add server name

    on it. I would like to indentify which web server are respond for the request, where do I look to find name of the webserver was serve the client request.

    Thanks

  14. Using dedicated application for each of the website on the server is disastrous for web servers that have limited amount of RAM. One busy website could quickly run our of resources while the other not-so-busy websites are keeping their resources idle.

  15. where do I look to find name of the webserver was serve the client request.

    You would find it in on the client browser side by looking at the headers returned from the server. Plenty of plugins for FF and IE will show you this.

  16. Pingback: links for 2010-04-15 | LaptopHeaven's Blog

  17. When we have had problems with one of our apps we have been stopping and starting the app pool. I believe this kicks all people off. Should we be using Recycling which from what I read tonight does not kick people off and does a smooth transition to a new worker process. Also, do you have any recommendations for how long we should allow for a worker process to finish and hand off work to new worker process? I think we are using 90 seconds. Feedback appreciated.

    • App Pool recycle does handle the graceful transition of requests, but I have seen it fail for many cases and especially make requests timeout due to the high warmup time of the newly spawned worker process. I always use load balancer and take the defective server out of load balancer, do the recycle and then put it back. This way, the impact to end users is minimal.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>