By default, ASP.net ships with a couple of inbuilt session state providers. These are responsible for making sure that when you access HttpContext.Current.Session, you get back whatever you stored in it last.

The default, and by far the easiest to work with, is something called InProc. This is short for "in-process" session storage; your ASP.net worker process dedicates a chunk of memory to keeping your session. It's very simple to work with. You don't need to set up any databases or key-value stores, and you don't need to worry about making your classes serialisable. Whatever you can allocate, you can stick in an InProc session. Unfortunately, this beguiling simplicity comes at a cost.

With InProc, you will lose the session storage as soon as any of the following happens:

  • IIS recycles the application pool (which will happen, amongst other things, any time you touch a config file)
  • Load balancing moves your user to a different server.
  • The ASP.net worker process is killed for any reason.

Of course, because you're storing your session in memory, the chances that IIS will want to recycle your application pool due to memory usage go up massively. It's a cruel world out there. And you might think you'll never need to kill the worker process, but it only takes one runaway application to put you in a situation where you have to choose between restoring normal service levels and not destroying your customer's shopping carts. Plus you have no hope of scaling without awkward things like configuring sticky load balancing. (With its own attendant problems, like the inability to take a server out of the load balance rotation without first waiting for all its active sessions to drain).

Basically, you can't entrust InProc session states with anything you don't mind losing unexpectedly. Which may be appropriate for some use cases, but at that point you're building a cache and ought to be asking yourself whether the session is the best solution. Not to mention that you run the risk of some well-intentioned developer coming along and putting something important in your otherwise ephemeral session state.

So what is there to be done? The best thing is to make your application stateless, at least from the server point of view. I'm a big fan of Javascript-based single page applications (SPAs) because you can make a great user experience with fast transitions between pages. But if you can't do that, and you must have a session - use a persistent session storage mechanism, decoupled from the web server itself. If your load is light than the default SqlServer session state mode will serve you fine - just be careful with scaling as multiple small requests isn't what SQL is designed to do. For bigger loads Microsoft offer a Redis-based session state provider, which also integrates nicely with Azure should you go down that route.

Critics may like to mention that these options require all the objects in your session to be serialisable. Which is a challenge if you're trying to rescue a legacy project (one I've had to face) - but if you're creating something new, then you shouldn't be throwing things in your session without thinking about what they are and how they're serialised. Failing to do so is a great way to end up with a web application that needs hundreds of megabytes of RAM per user.

In summary, then:

  • Think about what's going in your session.
  • Think about whether you even need a session.
  • If you do need session storage, don't use InProc for it.

Like so many things, InProc appears simple at first but rapidly leads you into a maintenance nightmare.