This is a big subject, but here are a few suggestions:
- Don't cache data that's unlikely to be reused, such as user-specific data
- Cache at all tiers: client, Silverlight (isolated storage), proxies, http.sys, IIS, ASP.NET cache object, ASP.NET per-request cache, SQL Server
- Use SqlDependency / SqlCacheDependency when you can, but don't over-use
- Avoid session state; use cookies instead when you can
- Leverage page and control (fragment) output caching
- Consider using cache validation when needed
- Consider light-weight alternatives to the ASP.NET cache object, such as weak memory refs
- When used correctly, SQL Server can act as a large cache
In case it helps, I cover this subject in detail in my book: Ultra-Fast ASP.NET.