1) Keep database connections down to as few and as quick as possible, 2) Cache frequently requested (but infrequently changed) data, such as site images, 3) Never try and cache connections (or ANY objects) in either session or application state, 4) Avoid using unneeded objects, and unneeded loops...
Connection pooling is handled automatically by IIS as far as I know. Never store connection objects in session or application state, as this stops IIS from pooling connections, and your site will keel over very quickly.
Try and use stored procedures, when possible. Create objects as late as possible, and destroy them as quickly. Use the .GetRows() or .GetString() methods to format data, rather than looping through a recordset, and close and destroy the objects.
Set up commonly requested data as cached, or manually cache some dynamic data in static HTML files which can be sourced off to the user, rather than negotiating with the database. Set IIS up to cache images for as long as is possible.
However, the most important thing to remember is the bandwidth. If you don't consider that, your application will severely be hindered.