Stateless vs Stateful
The stateless architectural pattern is probably one of the most important patterns in software architecture.
In fact, the stateless pattern is the one you must implement while developing the application.
So what is stateless architecture?
In stateless architecture, the application’s state is stored in only two places.
- The data store
- The user interface if there is any :)
No state is stored in the application code.
Now… So, if you are not sure what the state exactly is, you can think of it simply as Application’s Data either temporary or persistent
State = Application’s data either temporary or persistent
To understand it clearly what is stateful and stateless Let’s use an example:
In our example: Our application has a Login mechanism similar to any other application out there.
The application consists of the User interface, Login service and Database.
The user enters his username/password they are sent to the Login service which checks with the database whether that user exists or not? If so, the user data is retrieved from the database and is stored in a variable in the service(Login Service). So that in future requests, the application will be able to identify that user.
In this scenario, the state, which in this case the user details are stored in the application code, thus making it as stateful rather than stateless.
Now what is the problem with, why is this stateful code considered a bad thing?
To know why is stateful code is bad, We should understand 1. Scalability and 2. Redundancy
Scalability is the capability of the system to grow and shrink as needed. When there is a peak in the load of the system, A scalable system can simply add more resources and when not needed anymore these resources are removed. All these were done without any interruption of the system’s activity.
Redundancy means when a resource of the system stops functioning because of a system problem or because of a hardware glitch. The system will continue functioning using additional identical resources it has. And can also perform automatic scaling to other resources instead of the malfunctioning resource.
Example: With a system with more than one server,If one of our servers experiences electricity problems and shuts down, the system will be able to continue functioning with additional servers and perhaps even create a new server and add it to the existing ones.
These two concepts are cornerstone of any good architecture and must be taken into account when designing the system. Stateles architecture achieves this.
Now to implement this Scalability and Redundancy , Our architecture must look like this
As you can see we have more than one service(Login service) instance, exact number doesn’t really matter, but the best practice is to use atleast 3 instances.
In-front of the servers there is the LoadBalancer, A loadbalcer is an appliance or a software that has two roles in the architecture.
- Loadbalancer distributes the load between the servers — If one of the servers is very busy, the loadbalancer will know how to route the requests to another server.It will make sure no servers will crash under the heavy load. This capability supports the Scalability we need. Using the Loadbalancer we can add more servers as needed and just notify the loadbalancer of the new servers.
- Loadbalancer also checks the status of the servers and knows how to stop routing requests to malfunctioning ones. The way it works is that the loadbalancer sends periodically requests to its servers called Is Alive? requests. And expects to get a response with a positive answer. Any other response or no response at all will indicate that there is a problem with the server and the load-balancer will stop routing requests to the server. So this capability of Load-balacer has the strong support of redundancy. The Loadbalancer will allow the application to continue working even if one or more of the servers are down — this is what called as Redundancy
In stateless architecture Scalability and Redundancy tied to each other.
In Stateful applition will have a very hard time in achieving scalability and redundancy to match data across all servers you may need some kind of replication(DFS Replication) across servers.
If we look at our login scenario with multiple servers and a loadbalancer for the stateful application —
- first user logs-in, the request containing username, and password is sent and reaches the loadbalancer which routes it to server-1, then the server performs(using Log In Service shown below)the login process and keeps a variable for verifying the user in future requests in server-1 itself.
- Now the user performs another request, let’s say a user wants to add an item to a shopping cart(using Cart Service shown below). The request containing the item to be added is sent to the LoadBalancer- but this time LB routes it to server-2 .
- The request arrives at server-2, but this server has no idea who the user is, the data containing the user-data is on server-1, so in this case, the user will get an error message saying “user must login to the system before adding an item to cart”, which leave user confused😱😱 since the user logged-in already 😱😱
- The reason for the error is that “ the code is stateful”, the application code contains state or data, which is the user details in this case. additional resources or servers that are used for scalability(or)redundancy simply have no idea about the data in the code.
The statefullness of the code makes the application harder to scale and damge the user experience.
Now what would have happened in the “stateless architecture”
In the stateless case, the user-data will be saved in “some kind of datastore.” It could be a relational database, a NoSQL database, a distributed cache, or anything that can be accessed from all the servers.
When a request arrives at the server, it queries the datastore for the user details, and immediately knows exactly who the user is, regardless of the server that performs the actual login.
Note that this goes the same for redundancy, if the server that performs login was shutdown, the subsequent requests won’t be routed to it.
So this is the reason why stateless architecture is so important. It fully supports scalability and redundancy which makes the application much more reliable.
Conclusion: Always make your architecture stateless, there are almost no scenarios which justifies stateful architecture and you probably will never encounter them.