Phase 0
Statelessness and why it matters
Why servers are built to forget you between requests, and what that trade-off buys you later when a system needs to scale.

Interactive example
Stateful vs stateless servers
See what breaks when a second server enters the picture.
Stateful
The server remembers you in its own local memory.
- Fast to build for a single server.
- Breaks if that process crashes or restarts.
- A second server has no idea who you are.
- Hard to scale horizontally without 'sticky' routing.
HTTP forgets you on purpose
Log in on one request, make a second request a moment later, and by default the server treats you like a total stranger. No memory of the first exchange carries over unless something was deliberately built to carry it. That's statelessness, and it's not an oversight - it's the whole design.
What breaks if a server does remember
Say a server kept your session in its own local memory - your login, your cart, whatever you clicked last. Works fine right up until it doesn't:
- That process restarts (a deploy, a crash, autoscaling cycling instances) and everything it remembered about you is just gone.
- Traffic grows, you add a second server, and now there's a real question with no good answer: which one remembers you? Land on the wrong one and you're logged out for no reason you can see.
So where does "being logged in" actually live, then
Somewhere that isn't the individual server process. Two common answers:
A signed token, usually a JWT. Log in once, the server hands your browser a token, and every request after that carries it in the Authorization header. The server doesn't need to remember issuing it - it just checks the signature is valid each time. No lookup, no shared state, which is exactly why tokens got popular for anything that needs to scale across a lot of servers.
Or a session ID backed by shared storage. The server writes a session record somewhere every instance can reach - Redis is the usual choice - and gives the browser back just a small ID, typically in a cookie. Whichever server picks up the next request looks that ID up in the shared store. The process itself is still stateless. The memory just moved somewhere all of them can see.
Either way, notice what didn't happen: the state never lived inside one server's local memory. It got pushed onto the client, or onto something shared. That's the actual pattern worth keeping, more than the specific technology.
Where this genuinely doesn't apply
A live WebSocket connection for something like chat has to stay pinned to whichever process opened it - there's no getting around that, the connection itself is stateful by nature. Systems that need this usually solve it on purpose, with sticky routing or a dedicated service built to hold that state, rather than backing into it by accident. It's a deliberate exception carved out of the rule, not proof the rule doesn't hold.
This is also the idea that quietly underpins most of what "cloud-native" even means. Autoscaling, rolling deploys, a load balancerLoad balancerA component that sits in front of multiple servers and distributes incoming requests across them, so no single machine gets overwhelmed and a crashed instance doesn't take the whole system down. freely sending your request to whichever instance is least busy - all of it assumes any server can pick up any request without consequence. Take statelessness away and every one of those conveniences turns into a coordination problem instead.
Interview prep
This topic comes up in interviews - 3 questions, leveled by role.