10

I have been learning about stateful apps vs non-stateful, but I am still a bit confused on this topic.

For example, let's say I have an app running on Node where users are assigned to random rooms as soon as they connect through socket.io. These are rooms of 4 and not persistent in any way, but they are stored in a global variable as a hash map. I am not using a db (too many queries) nor redis (it's too expensive).

Is this an example of a stateful app or not?

1
  • 5
    If it was stateless there'd be nothing to store in the hashmap. Apr 28 '19 at 6:14
18

In the context of web applications, we call the server stateful if it maintains transient state in memory, rather than storing any data externally (e.g. in a database).

Stateful applications have a number of problems, for example:

  • you can't have more than one server running without pinning sessions to a particular server
  • the state is lost when the server is restarted

It is therefore a best practice to avoid server-side state (again: unless it is stored externally in a database).

Web app backends typically don't need to store any session state because they can use REST principles: state is transferred between the client and server. This state is represented by URLs, cookies, HTTP bodies, and so on. This is necessary because HTTP is a stateless protocol (semantically, not necessarily in its technical underpinnings).

With web sockets these principles break down a bit because the client is maintaining a long-duration session/connection with the server – and that connection involves state. This is unavoidable, but you do control whether and to what degree the use of websockets shall compromise an otherwise stateless backend design.

  • It is totally fine to maintain in-memory data structures that control which connection is subscribed to what events.

  • It is problematic if that in-memory data structure is the “source of truth” for that information.

    • If the subscriptions are supposed to be transient, everything is fine.
    • If you want re-establish the same subscriptions when a client re-connects, you need to store this state somewhere else. For example server-side in a database, or client-side via cookies or LocalStorage.

In general, maintaining internal server state is fine when one of the following applies

  • the state is stored externally
  • the state is not shared between requests
  • the state is just the acquisition of an expensive resource that can be reused, e.g. database connections
  • the state is a cache for some authoritative data source, although this gives rise to difficult problems such as cache invalidation and eventual consistency
2
  • 1
    I don't think being in memory is required, as "transient" here is more like a concept rather than the implementation. There are many implementation of session that uses database or file system to store session data, yet we still can't call it stateless.
    – tia
    Apr 28 '19 at 8:50
  • "It is therefore a best practice to avoid server-side state (again: unless it is stored externally in a database)" - I'd reconsider the term "best practice" here. Maybe there are situations where the business prefers connection lost over the cost of maintaining state etc. It really depends on the pros and cons per case.
    – Ron Klein
    May 1 '19 at 4:31
6

If you are storing state on the server that is needed in order to process an incoming request from the client, then the server is stateful. Said another way, it has state that it stores and needs to access in order to process requests from clients. So, your hashmap is state so your server is stateful.

Now, there are very few real web apps that do rich things that aren't stateful at all. After all, if you're going to have a user login and then process requests on the behest of a logged in client, then somewhat by definition, you're storing state on the server that pertains to a particular client and the server is stateful, even if just for the login info.

So, I wouldn't get too hung up on there being zero state on the server. What matters is how much state is there on the server, how expensive (in terms of processing, storage, etc...) is it to store and access this state and can you still scale your app horizontally with this state. And, wherever practical keep state in the client, not on the server. As a trivial example, suppose you have a client app that has a "next page" button. You could implement "next page" with either client-side state of server-side state.

If you had server-side state for the current page of the client, you could just send a command to the server that you'd like to view the "next" page. The server would look at its state for that client, increment the page and then return the data for the next page.

Or, you could store the current page on the client. When the client wants the next page, it takes its current page number, increments it by one and makes a generic request for the specific page number that it wants to view next.

Which of these implementations do you think scales better? Which is simpler to implement when the user opens a second tab viewing a different page? Which is simpler to horizontally scale. The answer to all of those is the one that does not store the current page on the server, but keeps it in the client and just makes generic requests for page N to the server. Keeping that state client-side makes it easier to scale individually and horizontally and support multiple views for the same client.

Not the answer you're looking for? Browse other questions tagged or ask your own question.