Concept · Requirements & scale
Stateless services
Move sessions and files out of the server so any instance can answer any request.
A service is stateless when any instance can handle any request, because nothing a later request depends on is kept in an instance's memory or local disk. That property is what lets you add instances behind a load balancer, replace them freely, and survive losing one.
Where state hides
| State | Problem | Where it should live |
|---|---|---|
| Sessions in memory | The next request may hit another instance | A signed cookie or token, or a shared store such as Redis |
| Uploaded files on local disk | Other instances can't see them; lost when the instance is replaced | Object storage |
| In-memory caches others rely on | Each instance has a different copy | A shared cache, or accept per-instance caches that may disagree briefly |
| Scheduled jobs | Every instance runs them | A scheduler with leader election, or a dedicated worker |
| Rate-limit counters | Each instance counts separately | A shared store |
Sticky sessions are a workaround, not a fix
Load balancers can pin a client to one instance (session affinity). It keeps in-memory sessions working, but load becomes uneven, scale-out helps only new clients, and an instance failure still logs its users out. Prefer moving the state.
What stateless doesn't mean
Stateless services still have state — it's just in a database, cache or object store designed to be shared, replicated and backed up. Long-lived connections (WebSockets) are a deliberate exception: the connection lives on one instance, so clients must be able to reconnect to any other and resume from durable state.
See vertical vs horizontal scaling and the System Design roadmap's scaling lesson.