Stateful vs Stateless Architecture

Updated June 3, 2026
M
Magic Magnets Team
7 min read

One of the most consequential architectural decisions you make when building a backend service is whether your servers hold onto client state between requests. This distinction — stateful vs stateless — determines how easily your system scales, how it recovers from failures, and how much operational complexity you inherit.

Stateful: The Server Remembers You

algobase.dev
A stateful server stores client context between requests — shopping cart contents, session data, in-progress operations — in the server's own memory. This creates a hard dependency: subsequent requests from that user must go back to the same server. This is solved with "sticky sessions" (session affinity), where the load balancer tracks which server each user is pinned to. The problems compound quickly. Load balancing becomes uneven — some servers are overloaded while others sit idle because they happen to have fewer pinned users. Server failures are catastrophic: if your server crashes, all sessions on that server are lost and those users are logged out mid-session. Deployments require careful session draining. Scaling requires moving session data between servers. Every advantage of having multiple servers is diminished.
1 / 1

Stateful — sticky sessions, uneven load, session lost on failure

A stateful server stores information about a client between requests. It remembers who you are, what you've done, and what you're in the middle of.

Classic examples: a traditional gaming server that keeps your position and inventory in memory; an old-school web app that stores your shopping cart in server-side memory; a TCP connection where the server tracks the connection state.

The experience feels seamless. The server has context. It doesn't need you to re-identify yourself on every request.

The problem: that context is tied to a specific server. If your load balancer sends your next request to a different server, that server has no idea who you are or what you were doing. You lose your session. Your cart is gone.

This forces a technique called sticky sessions (or session affinity) — the load balancer is configured to always send a specific user to the same server. And now you've lost one of the main benefits of having multiple servers in the first place.

What happens when that specific server goes down? The user's session is lost. Worse, the load balancer now can't evenly distribute traffic — some servers end up overloaded while others sit idle.

Quiz Time

What is the core scaling problem that sticky sessions introduce in a stateful architecture?

Stateless: Every Request Stands Alone

algobase.dev
A stateless server treats every request as self-contained. Any server can handle any request because no session data lives in application memory — it's externalized to Redis. The client carries a session ID (in a cookie) or a JWT containing the user's identity. Any server that receives the request can look up the session from Redis in under a millisecond, or verify the JWT cryptographically without any lookup at all. When Server A crashes, the load balancer routes the next request to Server B — it handles it identically. Load balancing is perfectly even. Scaling is trivial: spin up 50 more servers and they immediately join the pool. Deployments are simple: kill any server at any time. The small cost is a Redis lookup per request (or a few milliseconds of JWT verification) — a price worth paying for the operational simplicity.
1 / 1

Stateless — any server handles any request, state in Redis

A stateless server treats every request as if it's seeing the client for the first time. The request must contain everything the server needs to process it — authentication, context, parameters. Nothing is stored on the server between calls.

This is how REST was designed to work. Each HTTP request is self-contained.

What this enables:

  • Any server in your fleet can handle any request
  • No sticky sessions needed
  • Load balancing becomes trivially even
  • Servers can be added or removed without affecting clients
  • A server dying loses no client data — the next request just goes to another server

The trade-off: the client (or some shared store) has to carry more information per request. Authentication tokens, session IDs, user context — something has to track this. It doesn't disappear; it just moves somewhere else.

Quiz Time

A stateless server stores no state at all — all application data is derived purely from each incoming request.

Externalizing State

Here's the key insight: going stateless doesn't mean having no state. It means moving state out of your application servers and into dedicated storage that all servers can access.

Sessions in Redis

Instead of storing a user's session in the application server's memory, you store it in Redis with a session ID. The client holds the session ID (usually in a cookie). On every request, any server can look up the session from Redis in a millisecond.

Request: GET /dashboard Cookie: session_id=abc123 Server A: → looks up session abc123 in Redis → gets { userId: 42, role: 'admin' } → handles request

Server B could handle the next request identically. It doesn't matter. The state lives in Redis, not in Server A's memory.

Quiz Time

Which approach allows any server in a fleet to handle a user's authenticated request without calling a shared session store?

JWT Tokens

JSON Web Tokens take a different approach: put the state in the token itself. A JWT is a cryptographically signed blob that contains claims — userId, role, expiration time. Because it's signed with a secret key, the server can verify it without looking anything up.

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... // decoded payload: { userId: 42, role: 'admin', exp: 1748940000 }

No database lookup required. Completely stateless. The trade-off: you can't revoke a JWT before it expires (without introducing a token blacklist, which puts you back in stateful territory).

Quiz Time

How does JWT-based authentication achieve statelessness?

Why Stateless Is Preferred at Scale

ConcernStatefulStateless
Horizontal scalingHard (sticky sessions)Easy (any server handles any request)
Failure recoverySession lost if server diesNext request routes normally
Load balancingUneven (session affinity)Perfectly even
DeploymentTricky (draining sessions)Simple (kill server anytime)
ComplexityState lives in app serverState externalized to Redis/DB

The story is pretty clear. Stateless wins at scale. The cost is a small bit of added latency (a Redis lookup per request) or slightly larger request payloads (with JWTs). Both are worth it.

Practical note: Most modern web frameworks default to stateless design. Express, FastAPI, Spring Boot — they all encourage you to externalize sessions. The default has shifted because the industry learned this lesson the hard way.

Quiz Time

JWT tokens can be revoked before they expire without any additional infrastructure.

Where Stateful Still Makes Sense

Stateless isn't always the right answer:

  • Real-time connections: WebSocket connections are inherently stateful — the connection itself carries state. But you manage this by using a message broker (like Redis Pub/Sub or Kafka) so any server can route messages, even if the connection lives on one server.
  • Long-running computations: If a task takes minutes and requires in-memory state, it might make sense to let it live on one machine. Use a work queue, not direct connections.
  • Game servers: Position, physics simulation, and game state are often better in-memory for performance reasons. Dedicated game servers with session affinity are a legitimate pattern here.
Quiz Time

WebSocket connections are an example of where stateful architecture is still appropriate.

Summary

Stateful servers remember client context between requests — convenient but problematic at scale because requests must return to the same server. Stateless servers treat every request as self-contained, enabling any server to handle any request and making horizontal scaling trivial. The key technique is externalizing state: sessions go into Redis, authentication context goes into JWT tokens or database-backed sessions. Stateless design is the default choice for web services at scale because it enables even load balancing, simple failure recovery, and frictionless horizontal scaling.

How helpful was this content?

Comments

0/2000

Sign in to join the discussion

Saved on this device only

Sign in to sync progress across devices