Stateless Applications are an Illusion
Stateless applications have haunted me over the years. There is a mantra for web development: Keep your application stateless. I have seen companies pilling money on the effort to go stateless with their web applications. I’ve encountered a company with a multi million lines of code application with a stateful web framework going coniserable lengths to reengineer the app to being stateless. I have seen companies who don’t scale because they wanted to be stateless. All of this haunted me. Because it should not haunt you as a developer, I will take a deeper look and show that it’s impossible to keep most applications stateless.
To begin with, I divide state into two kinds:
- Application state (like Orders)
- Conversational state (temporary state during a session)
Some applications do not need state, or only have application state. The viewing part of CMS for example. One view sees applications as state machines and the essence of web requests to change this state. Beside the two kinds of state, there are at least two dimensions of state:
- accidental, framework state
- use case driven state, often the conversational state from above
The first dimension of state, framework state, can be designed away. There are frameworks which keep state during their operation – Tapestry for example. By chosing the right framework and architecture, you can minimize or prevent framework state. The second dimension cannot be designed away. If your use case calls for state, you need to store that state. A checkout process comes to mind: customers choose over serveral pages delivery address and payment information. Baskets come to mind: they store their conntent often only during a session. That conversation state needs to be hold somewhere.
When people talk about stateless applications, they in fact mean no state in the web tier. But state can be stored in several layers:
- Pages (e.g. with JS variables or Hidden fields)
- Easiest state store: Web Tier (HTTPSession in Java applications)
- Infrastructure (Cache like Memcached, Databases like MySQL, NoSQL like Redis)
You need to decide where to put your conversation state, but you cannot prevent your app from having state if the use case calls for it. What about using the easiest and fastest state store, your web tier? ThePlay framework says:
But this is much better because a session is not the place to cache your application data!
Contrary to this, your web tier session is a very good place to cache your application data. Problems do not arise when your web session is a cache (might arise if you do not handle stale data, but every cache has that problem), and can be constructed easily with the help from a persistent state store. e.g. store the UserId in a persistent store like Redis, cache the User object in your session. In case of a session failover, the new server will reconstruct the session from your persistent state store. Many developers do not like web tier state because your web tier does not allow easy failover and scaling. But when thinking the session as a cache, not a state store, no problems arise in case of taking down one web tier server.
As always there are trade offs, there is no best solution, be it web tier caching or “stateless” applications. As a developer you need to decide between the different trade offs of state storage.