Skip to content
HLD Learn/Three-Tier Architecture & Scaling Up
Browsing as a guest. Sign in to save your progress and earn XP as you complete chapters.

Stateless Services & Session Handling

6 min read

You'll learn to

  • -Define state, and explain why keeping it in one server's memory breaks horizontal scaling
  • -Work out with numbers how often a user is logged out when sessions live in server memory
  • -Explain why sticky sessions are an anti-pattern
  • -Compare a shared session store with signed tokens, and name the trade-off of each

Tip: the highlighter is on - just select any text below to mark it. Use the highlighter button up top to change color or turn it off. Highlights are saved on this device only. Log in to save them to your account instead.

Everything in this module has been building toward one practical question: if a user logs in on server A, and their next request is routed by the load balancer to server B, how does server B know who they are? Get this wrong and horizontal scaling breaks in a way that is easy to miss in a demo and painful in production.

What Is State, Exactly?

State is anything a server has to remember between one request and the next. Whether you are logged in, what is in your basket, the half-finished upload of a large file, how many requests you have made this minute: all of it is state. A stateless server is one that keeps none of it itself. Each request carries (or points to) everything the server needs, so any server can handle it, and a server can be added, removed or restarted without anyone losing anything.

The Failure, in Numbers

Suppose you run three servers and each keeps login sessions in its own memory. Sam logs in and the load balancer sends that request to server A, which stores that Sam is logged in. Sam clicks to another page. With requests spread evenly, the chance it lands on A again is one in three. Two times in three it lands on B or C, which have never heard of Sam, so they answer: please log in. From Sam's side the site randomly logs them out on about two clicks in three. With one server this bug cannot exist; it appears the day you scale out.

An Analogy: The Coat Check

Think of a theatre cloakroom. In the badly designed version, each attendant hangs coats on their own private rack, and you can only collect your coat from the attendant who took it. If that attendant is on a break, you wait; if they go home, your coat goes with them. In a better design there is one central cloakroom that every attendant can reach, and you are given a numbered ticket. Any attendant can read your ticket and fetch the coat. And in some situations the best design is that you keep your coat with you, so nobody has to store anything at all.

  • -Each attendant's private rack is session data held in one server's memory.
  • -Insisting on the same attendant is a sticky session.
  • -The central cloakroom is a shared session store, usually Redis, a very fast in-memory database that every server can reach.
  • -The numbered ticket is the session ID, which the browser holds in a cookie.
  • -Carrying your coat yourself is a token: the session data itself, signed, held by the client.

The Anti-Pattern: Sticky Sessions

One tempting fix is to configure the load balancer so that a given user always reaches the same server, for example by hashing the IP address. It works, but it quietly brings back the problem you were solving, in three ways:

  • -A crash loses sessions: if server A fails, every user pinned to it is logged out at once.
  • -Load becomes uneven: if heavy users happen to be pinned to the same server, it saturates while the others sit idle.
  • -Deploys and scaling hurt: restarting a server drops its users, and a newly added server starts empty while existing users stay pinned to the old ones.

The Real Fix: Push State Out of the Server

  • -Shared session store: session data lives in a fast external store (usually Redis) that every server can read. Any server can serve any user, and losing a server loses nothing. The browser holds only a session ID.
  • -Tokens (for example JWTs): the session data is encoded into a signed token that the client holds and sends with every request. No server-side lookup is needed; the signature proves the token is genuine and has not been altered.

In a diagram, the servers become interchangeable because they all read the same store:

Client
Load Balancer
Server A
Server B
Session Store

Each approach has a price. A shared store adds one extra network call per request (often under a millisecond to a couple of milliseconds) and becomes a critical dependency, so it must itself be replicated. A token needs no lookup, but the server cannot easily cancel it before it expires: if a token leaks, it keeps working until its expiry time unless you keep a deny-list, which is state again. Many systems use short-lived tokens plus a way to refresh them, to keep that window small.

Other Places State Hides

Sessions are the famous case, but state sneaks in elsewhere, and each instance breaks scaling out in the same way:

  • -Files on local disk: a user uploads a photo to server A's disk, and server B cannot find it. Store uploads in shared object storage instead.
  • -In-memory counters and caches: a limit of 100 requests a minute enforced separately on each of five servers quietly becomes 500. Keep such counters in a shared store.
  • -Scheduled jobs: a job meant to run once a night runs five times if it is on every server. Run it from one place, or take a lock first.

This is the same "push state to external storage" idea you'll see again and again: it's exactly what makes the Cache module possible, and it's the same instinct behind moving long jobs to background Workers later in the course.

In one line: a stateless server remembers nothing between requests, so any server can answer any request. Keep sessions in a shared store or in signed tokens, never in one server's memory, and do not rely on sticky sessions.

Interview Signal

How do you keep a user logged in across multiple stateless servers?

Weak Answer

"Store their session in the server's memory after they log in."

Strong Answer

"That breaks the moment the load balancer sends their next request to a different server. Instead: either every server reads/writes session data from a shared store like Redis (sub-millisecond lookups, and any server can serve any user), or skip server-side storage entirely with a signed JWT the client holds, trading an external dependency for a harder-to-revoke token."

Check Yourself1 / 5

What is the main risk of "sticky sessions" (routing a user to the same server every time)?

Ready to Build This?

Level 2: The 3-Tier Web App asks you to build exactly this shape, a load balancer in front of multiple stateless web servers, talking to a single database. Go build it, then come back for Databases 101.

Discussion0

Join the Discussion

Sign in to leave comments, reply to others, or like insights.

Sign In to ScaleDojo

No comments yet. Be the first to start the thread!