Introduction
From the intro to CS classes where we are programming "restaurant ordering software" and "tic tac toe games", we are taught that classes let you store state and behavior mutating that data in the same place. To me this always sounded like a sane way of doing things, everything has it's own state and communicate with it to change it's state. Shortly after, I was writing my first web service and was surprised to find out that my OrdersClass, which stored a list of a user's orders as an attribute, only ever held 1 single item in the array at any given request. I had just discovered that similar most major backend web frameworks Rails was stateless, and what I was looking for between requests persisting the mutated was called "stateful".
Stateful
This discovery led me into learning the difference between stateful and stateless services. The mental model behind stateful is pretty similar to how we are taught OOP. An object has a state, you mutate the state, and on the next call you get the new state that has been mutated, it remembers what you did to it, and does not reconstruct itself from scratch.
Think of a number summing service, it takes a number and returns the sum of all numbers ever sent to the service.
The interaction with this service would look something like this:
Between each request it remembered what the previous request did to the object's state. Unless we restart the service it will persist it's last state even on the next request.
Stateless
The mental model for statelessness is that every time you interact with a stateless service you will be interacting with a clean slate every time, all the objects would be initialized just for you with their initial state as their stored state(mostly). Let's go back to the number summing service example, what would happen if this service was stateless?
You get the idea, not very useful for data that needs to be persisted. So how would you create a stateless service that works correctly? We would take the data that needs to be persisted/stored/remembered and write in some sort of storage (a database, a file, a cache), just any external process that is not recreated on every request.
Real World Scenario
Now from the first glance stateful seems a lot more simpler, and almost all applications you use work like they are stateful (facebook wont make you signup everytime you want to go on it, you signup once and it will remember). Yet most web services written in production today are stateless.
Imagine if we have a lot of users and one server is just does not have enough throughput (requests/second) to handle the traffic without compromising latency. So we decide instead of running our number running service on a single server we will distribute our user traffic across 2 servers running an instance of the number summing service.
A stateful scenario
If our service is stateful, they will both hold a different sum, and if you add a number to server A, you will only get the right answer if you retrieve the state stored in number A, this means that scaling horizontally and distributing load evenly across multiple machines will now become harder, because every request has to go to the same server it went to previously. Imagine mapping every request to where it was first hit... in short you messed up should have been smarter and gone the stateless route.
A stateless scenario
Now imagine the same scenario with multiple servers running number summing service with traffic being routed/distributed evenly between those 2 servers. Since they are stateless and they store their state in an external database, each server uses the same source of truth, and does not care which server the request initially hit. This makes horizontally scaling a lot easier, and reduces the complexity of the load balancer trying to figure out which request goes to which server, you can just alternate between the 2 servers, or go round robin between multiple servers.
Great post. This gives a good description of how to build a stateless service that still has some “state” to it like users expect.
Thank you!