Stateful vs Stateless Microservice Applications

What is difference between stateless and stateful application?

This is one of the most common question that you may have and if you search for an answer about it to fundamentally understand what exactly the real difference is - you would only come across the basic definitions such as stateless applications do not maintain the state whereas stateful applications stores the state. Each request in stateless applications can work in isolation, however, that is not the case for stateful applications and so on. However, what exactly is the core difference between stateful and stateless microservices, we would understand about the basic difference of it in this article.

stateful vs stateless applications



Breaking The Myth - Stateful vs Stateless microservices

Per my viewpoint, it's not 100% true that only stateful application services store the state and stateless application services do not store. Infact, it is possible that stateless services also store the state in some way or the other, in persistent store. When it comes to stateful applications, they generally maintain the state in session in-memory along with persisting it in the persistent store. Having an in-memory session makes stateful applications to be more faster in comparison to stateless applications. However, you must be surprised to know that, in the modern world of API development, stateless APIs are the preferred choice for building the scalable systems and there are reasons behind it.

Why it is important to make microservices stateless?

Let's continue with our earlier discussion of the faster performance of stateful applications. In this case, the limitation that we end up with is that scalability becomes an issue due to the sticky sessions and it's challenging to horizontally scale the stateful applications.

Having that said, it would be a good idea to understand this with an example in the context of stateless service as well as stateful service. 

Let's say your api service is deployed on 3 nodes and user's are hitting the api request, you have a load balancer in between which would route the api requests to any of the 3 nodes. The good part about stateless services is that, any of the node would be able to serve the api request. The reason is - there isn't a state maintained explicitly in-memory. This makes it very easy to scale stateless services. As the load increases, you may scale horizontally by spinning up a new node and deploy your service and you are ready to cater to the heavy load. This is not the case with stateful services. 

In the same scenario mentioned above, wherein we have 3 nodes and a load balancer, there needs to be sticky sessions maintained between the client and the server. What that means in simple words is - all the requests for a given client should go to a single dedicated node. This indicates that, you will not be making an effective usage of all of your nodes. It may be possible that, one of your node is busy serving the requests and other nodes are just seating idle. Another limitation that you will have from scaling perspective is that - as stateful applications maintain the state in-memory, that means it can't go beyond to serve more requests due to the memory limitations, as the node would have been allocated a specific amount of memory. 

Hence, while building the modern world applications with the aim of high scalability, it's important to have the stateless api services, because statelessness is the fundamental aspect of scalability.

Scaling stateful services

Now, it may still be possible that for some of the services, you have to have stateful services. In such scenarios, what are the ways to achieve scalability for stateful services? Yes, there are proven ways and there are well-established frameworks those provide this capability. In the earlier example wherein due to stick sessions we were having a possibility of a single node getting heave loaded with the requests, this scenario can be addressed having the back-pressure technique wherein a node should start rejecting the requests after the defined threshold is reached. With this, it's now possible that a request can go to any of the node. Then, what about statefulness? This routing strategy can be effectively implemented using gossip protocols and consitent hashing or distributed hashtables. This is altogether a separate topic which can be discussed in detail, however, to give you an idea I have tried to summarize it at a high-level here.

Summary

To summarize the basic difference between stateless and stateful, stateless services are easily scalable (a request can easily be served by any node, also it is easy to add new nodes as and when load increases, there is no limitation from the memory perspective as there is no state being held in-memory). Stateful services in one way offer faster performance by maintaining the state in-memory, however, from scalability perspective they do not scale well in comparison to stateless services due to memory limitations and sticky session limitations. Although there are ways to achieve scalability for stateful services, however, you need to use well-established and proven frameworks for it.