HT
How Things Work
System Online

Authentication at Scale

How identity survives horizontal scaling — stateful server sessions vs stateless JWTs, OAuth2/OIDC single sign-on, and the access-token + refresh-token hybrid that balances scale with revocation.

How It Works

Once a system runs on many servers, where you keep auth state becomes an architectural decision. Server sessions keep state centrally (simple, revocable, but needs a shared store). JWTs make each token self-validating (scales effortlessly, but hard to revoke). Production systems usually combine short-lived JWTs with revocable refresh tokens behind OAuth2/OIDC.

1
Authentication vs Authorization

Authentication answers 'who are you?' (login). Authorization answers 'what may you do?' (roles/permissions). After login the server issues a credential the client presents on every later request so it doesn't re-authenticate each time.

2
Server Sessions (Stateful)

The server stores session state and hands the client an opaque session-id cookie. On each request it looks up that id in a store to find the user. Simple and instantly revocable (delete the row) — but with many app servers the session store must be shared (Redis), adding a dependency and a lookup hop.

3
JWT / Tokens (Stateless)

The server signs a token containing the user's claims. Any server can verify the signature locally and trust the claims — no shared store, no lookup. This scales out beautifully. The trade-off: a signed token can't be un-signed, so revocation before expiry is hard.

4
OAuth2 / OIDC & the Hybrid

Real systems delegate login to an identity provider via OAuth2/OpenID Connect (SSO), which returns tokens. To balance scale and revocation, they use short-lived access tokens (JWT, ~15min) plus a long-lived refresh token that IS checked against a store — so you get stateless validation on the hot path and revocation where it counts.

Key Concepts

🍪Session (Stateful)

Auth state lives on the server, keyed by an opaque cookie. Instantly revocable; needs a shared store to scale out.

🎫JWT (Stateless)

A signed token carrying the user's claims. Verified locally with no store lookup — ideal for horizontal scale.

🔄Access vs Refresh Token

A short-lived access token (used per request) plus a long-lived refresh token (exchanged for new access tokens, revocable).

🔐OAuth2 / OIDC

Delegated auth: an identity provider authenticates the user and issues tokens, enabling SSO across apps.

🚫Revocation

Invalidating a credential before expiry. Trivial for sessions, hard for pure JWTs — hence short TTLs + refresh.

📌Sticky Sessions

Pinning a user to one server so in-memory session data survives — a crutch that a shared store or JWT removes.

Stateless JWT + revocable refresh
tsx
1// Stateless JWT: verify locally on every server, no store lookup.
2const token = jwt.sign(
3 { sub: user.id, role: user.role },
4 PRIVATE_KEY,
5 { algorithm: "RS256", expiresIn: "15m" } // short-lived!
6);
7
8// Any app server validates with the PUBLIC key — zero shared state:
9const claims = jwt.verify(bearer, PUBLIC_KEY, { algorithms: ["RS256"] });
10
11// The catch: you can't un-sign a token. Solve revocation with
12// SHORT access tokens + a refresh token you CAN revoke server-side:
13app.post("/refresh", async (req, res) => {
14 const rt = req.cookies.refresh;
15 if (await isRevoked(rt)) return res.sendStatus(401); // checked store
16 res.json({ access: signAccess(rt.user), expiresIn: "15m" });
17});
💡
Why This Matters

Auth touches every request and every security incident. The session-vs-token trade-off (statefulness, revocation, scale) is a classic interview question, and getting it wrong causes real bugs — random logouts when scaling, or tokens that outlive a logout. Understanding OAuth2/OIDC and the refresh-token pattern is essential for any multi-server system.

Common Pitfalls

Storing sessions in local server memory — breaks the moment you run more than one instance.
Long-lived JWTs with no revocation path — a leaked or post-logout token stays valid for its full lifetime.
Putting sensitive or large data inside a JWT — it's only signed, not encrypted, and it's sent on every request.
Skipping signature/issuer/audience/expiry validation — accepting unverified tokens is a critical vulnerability.
Rolling your own crypto/auth instead of a vetted library or identity provider (OIDC).
Real-World Use Cases

1Logout Doesn't Log Out

Scenario

A security team reports that after a user clicks 'log out' (or an admin disables an account), the old JWT keeps working for up to an hour until it expires.

Problem

Pure JWTs are stateless and self-validating — the server never checks a store, so there's nothing to flip to invalidate an outstanding token. Long token lifetimes made the window dangerous.

Solution

Shorten access-token TTL to ~15 minutes and move long-term sessions to a revocable refresh token checked against a store. On logout/disable, revoke the refresh token (and optionally maintain a small deny-list of access-token jti values). The next refresh fails, closing the window.

💡

Takeaway: Stateless tokens trade revocability for scale. Short access tokens + a revocable refresh token restore control without putting a store lookup on every request.

2Sessions Break When You Scale Out

Scenario

An app that ran fine on one server starts logging users out randomly after the team scales to four instances behind a load balancer.

Problem

Sessions were stored in each server's local memory. The load balancer sent a user's next request to a different instance that had never seen their session, so it looked like they weren't logged in.

Solution

Move session storage to a shared external store (Redis) that every instance reads, so any server can validate any session. (Sticky sessions are a weaker fallback.) Alternatively switch to stateless JWTs to remove the shared dependency entirely.

💡

Takeaway: In-memory sessions are invisible-state that breaks horizontal scaling. Either externalize session state to a shared store or go stateless with tokens — never assume requests return to the same instance.

Join the discussion

Comments

?

Loading comments...

Cookie preferences

We use essential cookies for sign-in and preferences. With your permission, we also use basic analytics to improve lessons.