Is Your System Stateful or Stateless?
By: Łukasz Gebel
Tags: Software Architecture, Programming, Software Engineering, Technology, Software Development

Is Your System Stateful or Stateless?

Different perspectives on obvious concepts

Photo by cloudvisual.co.uk on Unsplash

Statefulness and statelessness seem to be quite obvious properties of applications and computer systems in general. However, if we think deeply about these properties of systems it turns out that classifying a solution as stateful or stateless is more complicated. Let’s go through different perspectives on this problem.

State, state everywhere

First of all, we need to define what we mean by using the term “state”. Imagine that someone asks you what is a state? How would you describe it using your own words?

It’s not so simple. The state is quite a primitive idea, and primitive ideas are hard to define due to their simplicity. It’s a little bit like a set in Maths. If I had to define state I would say it’s a set of properties of a given object. These properties describe the object so we can understand and interact with it.

We can also get professional help and check the definition in a dictionary [1]:

“A condition or way of being that exists at a particular time”

Pretty neat, isn’t it? This definition is built from two main components. The first one is about ”a condition or a way of being”. This part focuses on the properties of something. The second part is about “existing at a particular time”. It adds some dynamics. As a result, the state is not only a set of properties, these properties exist at the given time, like a snapshot. They could be different in the past and they can change in the future.

My favorite example of state definition using the real-life object is a light switch. It has two states: on and off.

Real-life concepts are reflected in computer science. The same applies to the state. Let’s check its definition in the digital world [2]:

“(…) a program is described as stateful if it is designed

to remember preceding events or user interactions.”

Ok, so it’s about remembering the way of interacting with a program or a system. For example, we could interact by saving a file or sending requests. These actions affect how the system responds. Let’s follow the definition:

“The remembered information is called the state of the

system.”

Finally, we have a sharp and clear description of the state in the computer science world. But when you try to apply this definition, you’ll realize that almost every system can be called stateful. Remembered information is in files, databases, but also in variables that are used to write the code. State is everywhere.

Fortunately, there are different contexts. Let’s have a look at three common architectures that can be described as stateful or stateless.

Fully Stateless System Architecture

Fully stateless architecture (image by Author).

In the picture you can see 3 main elements of architectures we’ll discuss:

Clients sending requests Load Balancer dispatching requests Servers handling requests

The first approach is fully stateless. It means that every request can be handled independently by any server. There is no need to keep information about preceding requests or do synchronization between servers when different requests from the same client land on different machines.

All the state that is needed to handle request can be easily created while processing it, without any third-party components. It doesn’t mean there is no state at all. Each server may have its own data source stored in local DBs, files, or cache. Important thing is that servers are independent.

Such architecture is truly scalable. In the case of load changes, we can add or remove nodes so the system’s capacity is sufficient. We can start small and then easily scale out. It’s a powerful benefit.

Fully Stateful System Architecture

Fully stateful architecture (image by Author).

The second approach is fully stateful design. Here we have something called “sticky load balancer”. It is capable of keeping track of client sessions and redirecting all requests from a given client to the same server.

The sticky load balancer may use different information to dispatch requests to the proper server. Some examples are a source or destination IP addresses, ports, protocols.

Servers need to have and keep all state needed to correctly handle requests. Requests cannot be handled independently as preceding calls can affect how the system should deal with the new ones. They could change the state of the local database, file, or cache.

Such architecture is not very scalable. Actually, the only way to scale it on the go is to scale up. It means you can give your node more resources, for instance, RAM or CPU. However, such vertical scaling very often means that you need to stop your server, scale up, and start again. And it means outage.

I like to joke about this architecture and call it “awfully stateful”. Scaling is not the only problem. Let’s say your server evaporates, which is highly probably in cloud environments. In such a case, you lost all information needed to handle your clients’ requests. Not good.

I’m not a fan of strong, definitive statements as very often the correct answer is “it depends”. So if you’re fully aware of all drawbacks of this approach it’s ok to use it. But you need to be careful and check if different approaches don’t fit your needs in a better way.

Stateful or Stateless?

Stateful or stateless architecture (image by Author)?

The last approach we’ll discuss is quite controversial. But let’s start by describing it. In this architecture, we have the same simple Load Balancer that we had in the first approach (without sticky sessions). The only difference is that we have an additional stateful component, or cluster of components (in the picture it’s shown as DB).

Servers are handling requests and get all needed information from the stateful component. Requests affect each other, however, they can be handled independently by any of the servers. We need to take care of the consistency of our data, transactions may be needed in some cases, but we gained freedom while choosing the server which should handle the request.

Thanks to that we can scale out our servers. A new node will just get the requests, connect to DB or cache, and process it correctly. The stateful component also can be scalable. We can put a cluster of DBs or cache and prepare the system to be ready for load fluctuations.

The main drawback is a bigger complexity. It’s harder to write and maintain such a distributed system rather than keep everything on a single server. But with great power there comes great responsibility. It’s worth to work on well-structured architecture now and save yourself from troubles in the future.

So where’s the controversy? Actually, some people think such architecture is stateless. You delegated your state to a third-party component (DB, Cache) so your system is not stateful. But wait, what about this “third-party” component that is a crucial part of a system? No worries… it’s third-party right [3]?

The other side (including me) thinks that such systems are stateful. We cannot just forget about the part of our system that is needed to make it work, call it third-party or delegated state component and pretend it’s not there. If you cannot get rid of it from your architecture it is stateful, even if you don’t like it.

Verdict

We philosophized a little bit about the nature and definition of state to have a better understanding of the discussed topic. Then we went through 3 general system architectures that deal with, or don’t have to deal with the state. To which category your system belongs? What’s your opinion about the last approach? I encourage you to take a closer look at your design and make sure you’re ready for changes and your system evolution. Oh, and the last thing, don’t stick to awfully stateful architecture.

Bibliography: