Authentication on the web often feels confusing not because it is complicated, but because its core ideas are rarely explained in a clean order.
This post builds that order.
We will start from the nature of the web itself, explain cookies and server-side sessions as a single coherent model, then expand outward to JWT and why it fits modern distributed systems.
The goal is not to overwhelm you, but to give you a mental model you can reuse.
1. Why the Web Needs Help Remembering Users
The web is built on HTTP, which is stateless.
That means:
- Each request is independent
- The server does not remember previous requests by default
- Every request looks like a brand-new visitor
Yet real applications need to remember:
- Who the user is
- Whether they are authenticated
- Temporary state like preferences
So the first problem to solve is simple:
How can the server recognize the same user across multiple requests?
The answer begins with cookies.
2. Cookies and Server-Side Sessions: One Model, Two Roles
Cookies: identification on the client
A cookie is a small piece of data stored in the browser.
Important properties:
- Lives on the client (browser)
- Automatically sent with every request to the same domain
- Small and simple
- Treated as untrusted input by the server
Conceptually, a cookie often looks like:
session_id=abc123
A cookie does not contain meaning by itself.
It only identifies something.
Server-side sessions: state on the server
A server-side session is data stored by the backend.
It typically contains:
- User identity
- Authentication state
- Temporary per-user data
Example (server-side):
session_id: abc123
user_id: 42
role: admin
The browser never sees this data directly.
The core relationship
This is the most important idea in this post:
Cookies identify a user. e.g. Store session_id=abc123, each session_id maps to a session on the server.
Sessions store the user’s state. Each session_id maps to a real user’s data, e.g. user_id=42, role=admin.
They are not alternatives.
They are designed to work together.
3. How Cookie + Server-Side Session Works (End to End)
Let’s look at the full workflow.
What happens conceptually
- The browser sends a request
- The server creates or loads a session
- The server associates the session with a session ID
- The server sends the session ID back as a cookie
- The browser automatically includes the cookie in future requests
- The server uses the session to determine user state
Important:
- The browser does not know authentication logic
- The server makes all decisions on each request
This model fits naturally with server-rendered applications.
4. Cookies Are Transport, Not Architecture
A common misunderstanding is assuming that using cookies automatically means using server-side sessions.
That is not true.
Cookies are just a way to send data from client to server.
Two common patterns:
Cookie + server-side session
- Cookie contains a session ID
- Server loads session data from storage
- Identity lives on the server
Cookie + token (JWT)
- Cookie contains a signed token
- Server verifies the token directly
- No session lookup is required
So the correct mental model is:
Cookies are transport. e.g. Cookies can carry session IDs or JWTs.
Sessions and tokens are architectural choices. Session implies server-side state; JWT implies stateless verification.
5. Server-Side Sessions vs JWT: Two Different Tradeoffs
Server-side sessions
Characteristics:
- Stateful
- Server retains full control
- Easy to invalidate
- Sensitive data stays on the server
Best suited for:
- Server-side rendered apps
- Admin interfaces
- Systems prioritizing control and simplicity
JWT (JSON Web Token)
JWT takes a different approach:
The user’s identity is embedded inside the token itself.
JWT flow:
JWT contains:
- User identity
- Claims or roles
- Expiration time
- Cryptographic signature
The server verifies the token but does not store session state.
6. Why JWT Became Popular in Distributed Systems
Before understanding why JWT fits modern systems, we need to recognize the challenges of using server-side sessions in distributed environments.
Challenges of server-side sessions in distributed systems
In a distributed system with multiple backend services, if a user logs in, the session data is only created in one backend service. But the next request might go to a different service that does not have access to the session data. This requires all services to share a common session store (e.g., Redis), which adds complexity and potential bottlenecks. It counteracts the needs of scalability and independence among services.
How JWT solves these challenges
JWT aligns well with modern system constraints:
- Stateless services
- Horizontal scaling
- Microservice architectures
- Multiple client types (web, mobile, API)
Because no shared session store is required:
- Services are easier to scale
- Infrastructure coordination is reduced
More specifically:
- Decoupling: Each service can independently verify tokens without relying on a central session store.
- Performance: Reduces latency by eliminating session lookups.
- Flexibility: Works well across different domains and client types.
This is why many real systems adopt a hybrid approach:
- Server-side sessions at the web boundary
- JWT between APIs and services
Final Mental Model
To keep everything straight, remember this:
- Cookies are envelopes. They carry data between client and server.
- Sessions are filing cabinets. They store user state on the server.
- Session ID is the label on the envelope that points to the right filing cabinet. Session ID is stored in cookies so that it can be sent to the server.
- JWTs are self-contained passports. They carry identity and claims within themselves.
Each exists for a reason.
Understanding which problem each one solves is the foundation of designing authentication systems that are clear, scalable, and predictable.
Enjoyed this article? Support my work with a coffee ☕ on Ko-fi.