Stateless Servers: Why They Scale and Stateful Ones Don't
What Is a Stateless Server?
A stateless server stores no session or user-specific data locally. Every request carries everything the server needs to process it — the server itself is interchangeable.
Request 1 can be handled by Server A. Request 2 from the same user can be handled by Server B. Server B doesn't need to know what Server A did. It doesn't need to ask Server A anything.
Any server, any request. That's statelessness.
The Problem With Stateful Servers
The opposite — a stateful server — stores user session data in local memory. User logs in, session is stored in Server A's RAM. Their next request must also go to Server A because Server B doesn't have that session.
This creates sticky sessions — the load balancer has to pin each user to one server. Now:
- You can't freely distribute load (some servers get busy users, some get idle ones)
- If Server A crashes, all its sessions are gone — those users are logged out
- Deploying Server A means temporarily kicking out all pinned users
- Horizontal scaling becomes theater — you have more servers but can't use them freely
Common mistake
How Stateless Works in Practice
Move all session state out of the server and into a shared external store — typically Redis.
Instead of storing the session in Server A's RAM, you:
- Create the session
- Store it in Redis with a session ID
- Return the session ID as a cookie
- On every subsequent request, any server looks up the session ID in Redis
- Gets the session data, processes the request
All servers share the same Redis. Any server can handle any request.
| 1 | Before (stateful): |
| 2 | User → LB → Server A (has session in RAM) |
| 3 | User → LB → Server B (no session) → 401 |
| 4 | |
| 5 | After (stateless + Redis): |
| 6 | User → LB → Server A → Redis (session lookup) → ✓ |
| 7 | User → LB → Server B → Redis (session lookup) → ✓ |
Rule of thumb
What "Stateless" Actually Means for Your Code
A stateless server should not rely on:
- In-memory session stores (express-session defaults to this — dangerous)
- Local disk writes that need to be read by the same server later
- Instance-specific configuration that differs between servers
A stateless server can use:
- JWT tokens — self-contained, no server-side session needed
- Redis sessions — shared across all instances
- Database — always accessible from any server
- Shared object storage (S3, GCS) — for files
When This Matters Most
Statelessness becomes critical the moment you add a load balancer. But it's worth designing for from day one because:
- Auto-scaling — cloud providers spin up new server instances automatically; they have no existing state
- Deployments — rolling deploys replace servers; new servers start fresh
- Crash recovery — when a server crashes, requests need to continue on other servers without data loss
Note
Real World
Every major cloud-native application runs stateless app servers. AWS, GCP, and Azure's auto-scaling groups all assume stateless servers — they add and remove instances based on load, and any instance must be able to serve any request.
Netflix explicitly designed their servers to be "cattle, not pets" — any server can be killed and replaced without affecting users, because no server holds unique state.
Takeaways
- A stateless server stores no session data locally — any instance can handle any request
- Stateful servers create sticky sessions, which break horizontal scaling
- Move session state to Redis (shared across all instances)
- JWT tokens are another approach — the token carries state, no server storage needed
- Design for statelessness before adding a load balancer, not after
- Stateless servers enable auto-scaling, rolling deploys, and crash recovery