Do you have pages that do not write to a session?

Page requests using session state internally use a ReaderWriterLock to manage access to the session state. For pages that only read session data, consider setting EnableSessionState to ReadOnly.

<%@ Page EnableSessionState="ReadOnly" . . .%>

This is particularly useful when you use HTML frames. The default setting (due to ReaderWriterLock) serializes the page execution. By setting it to ReadOnly, you prevent blocking and allow more parallelism.

Do you check for nulls before accessing items in session state?

A common pitfall when retrieving data from session state is to not check to see if the data is null before accessing it and then catching the resulting exception. You should avoid this because exceptions are expensive. To find where your code accesses session state, you can search for the string "Session."

Do you store complex objects in session state?

Avoid storing complex objects in session state, particularly if you use an out-of-process session state store. When using out-of-process session state, objects have to be serialized and deserialized for each request, which decreases performance.

Do you store STA COM objects in session state?

Storing single-threaded apartment (STA) COM objects in session state causes thread affinity because the sessions are bound to the original thread on which the component is created. This severely affects both performance and scalability.

Make sure that you use the following page level attribute on any page that stores STA COM objects in session state.

<@%Page AspCompat = "true" %>

This forces the page to run from the STA thread pool, avoiding any costly apartment switch from the default multithreaded apartment (MTA) thread pool for ASP.NET. Where possible, avoid the use of STA COM objects.