Sessions vs JWT

You log into a site once, right? Then you click around:

  • You open your profile, then go to settings, then back to the homepage.
  • The site keeps showing your name and your stuff on every page.
  • But here’s the weird part. You never typed your password again. Not even once.

So how does the site remember who you are across all those clicks? You’d think it would forget you the moment you move to the next page. And honestly, by default, it does. The site has to do extra work to keep you logged in, and there are two main ways to do it: sessions and JWT. That’s what this lesson is about.

🎯 The Problem: HTTP Forgets You

To see why login is even tricky, you have to know one strange thing about how the web works:

  • The web runs on HTTP, the agreed format browsers and servers use to talk. We covered this in the URL lesson.
  • And HTTP is stateless. Stateless just means the server doesn’t remember anything between one request and the next. Each request shows up fresh, like the server is meeting you for the very first time.
  • So when you click to the next page, that’s a brand new request. The server has no built-in memory that you logged in two seconds ago.

Think of it like talking to someone with no short-term memory:

  • You tell them your name. They smile and say hi.
  • You walk out, walk back in, and they ask “who are you?” again.
  • Annoying, right? That’s the server on every single click.

So the real question becomes: how do we hand the server a little reminder of who we are, on every request, without typing the password each time? Both sessions and JWT are answers to exactly that question.

🍪 What is a Session?

The first answer is the session. Here’s the basic idea:

  • A session means the server stores your login state for you, in its own memory or a database.
  • When you log in, the server creates a little record like “this person is Alex, logged in, an admin.” That record is the session.
  • The server then gives your browser a session id. A session id is just a long random string, like a ticket number. It points to your record on the server.
  • That ticket gets stored in a cookie. A cookie is a small piece of data the browser saves and automatically sends back to the same site on every request.

So the cookie is the key, and the real data lives on the server. Let’s walk the flow:

  • You log in with your password. The server checks it, then creates a session record and a session id for you.
  • The server sends that session id back in a cookie. Your browser quietly stores it.
  • On your next click, the browser automatically attaches the cookie. So the request carries your session id along with it.
  • The server takes that id, looks up your record, and goes “ah, this is Alex.” It does this lookup on every request.

You log in

Server stores session

Server sends session id in cookie

Next request sends cookie back

Server looks up session

Server knows it is you

The session id is not your data

The cookie only holds a random id, like a coat-check ticket. It doesn’t hold your name or your role. All of that sits safely on the server, and the id just points to it. So even if someone reads the cookie, it’s only a meaningless string to them.

The big thing to notice: with sessions, the server is doing the remembering. We call this stateful, because the state, your login info, lives on the server side.

🎟️ What is a JWT?

The second answer flips that idea around. Instead of the server holding your data, what if you held it yourself? That’s a JWT.

  • JWT stands for JSON Web Token, and people say it like “jot.”
  • A JWT is a signed token that holds your info inside it. A token here just means a string the server hands you to prove who you are.
  • When you log in, the server builds this token, packs your details into it (like your user id and role), and signs it. Then it gives the whole token to you.
  • Your browser stores the token and sends it back on every request. The server reads it and trusts it, because the signature proves the server is the one who made it.

The key difference: the server does not store the token anywhere. It doesn’t look anything up. It just checks the signature and reads the data from the token itself. Let’s see the flow:

  • You log in. The server checks your password, then builds a token with your info and signs it.
  • The server sends the token to you. Your app stores it.
  • On every request, your app attaches the token.
  • The server verifies the signature. If it’s valid, the server reads your info straight from the token. No database lookup needed.

You log in

Server signs a token

Client stores the token

Token sent on each request

Server verifies signature

Server reads info, no lookup

What a JWT actually looks like

A JWT is just one long string with three parts, separated by dots:

header.payload.signature
eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjoiQWxleCJ9.K8s2_aB...

Let’s read the three parts:

  • Header: says what kind of token it is and how it was signed.
  • Payload: holds your actual data, like { "user": "Alex", "role": "admin" }. This is the useful bit.
  • Signature: the server’s stamp. It’s made from the header, the payload, and a secret key only the server knows.

The first two parts are just base64url encoded, which is a way to pack text into a URL-safe string. Here’s the part people always get wrong:

  • Base64url is not encryption. It’s not a secret code. Anyone can decode it and read the payload in plain sight.
  • The signature doesn’t hide the data. It only proves the data wasn’t changed. If someone edits the payload, the signature won’t match, and the server rejects it.

A JWT is signed, not encrypted

This is the single most important point about JWTs. The payload is readable by anyone who has the token. So never put secrets in it, no passwords, no card numbers, nothing private. The signature guarantees nobody tampered with it, but it does not hide what’s inside.

⚖️ Sessions vs JWT

Now let’s put them side by side. They’re solving the same problem in opposite ways, so the trade-offs line up nicely.

Aspect Sessions JWT
Where state lives On the server In the token, with the client
Server storage Needed (stateful) None needed (stateless)
Each request Server looks up the session Server just verifies the signature
Scaling across servers Harder, needs a shared store Easier, any server can verify
Logout / revoke Easy, just delete the session Hard, valid until it expires
Size sent each request Small (just an id) Larger (the whole token)

The one-line summary

With sessions, the server remembers you and the cookie is just a ticket. With JWT, you carry your own proof and the server only checks it. Everything else flows from that one difference.

🤔 Which Should You Use?

Both are good, they just fit different jobs. Here’s how to pick.

Reach for sessions when:

  • You’re building a normal web app, the kind with login pages and a browser. This is the safe default.
  • You need easy logout. Kicking someone out is instant, you just delete their session on the server.
  • You only have one app or a small setup, so a shared session store isn’t a big deal.

Reach for JWT when:

  • You’re building an API that lots of clients call, like a mobile app or other services talking to each other.
  • You have many servers and want any of them to handle a request without checking a shared store. The stateless nature really shines here.
  • You’re doing microservices, where one service can verify the token without calling back to a login service. (Microservices means splitting an app into small independent services.)

When in doubt

If you’re a beginner building a regular website, start with sessions. They’re simpler to reason about and logout just works. Reach for JWT once you actually have an API or multiple services that need stateless auth. Don’t pick JWT just because it sounds modern.

⚠️ Common Mistakes and Misconceptions

A few things trip people up constantly with this topic. Let’s clear them out:

  • “JWTs are encrypted, so the data is hidden.” No. They’re signed, not encrypted. Anyone holding the token can decode and read the payload. The signature only proves nobody changed it.
  • “I can store secrets in the JWT payload.” Please don’t. Since the payload is readable, putting a password or anything private in there is the same as handing it out. Keep it to ids and roles.
  • “JWTs can be revoked just as easily as sessions.” Not really. A JWT stays valid until it expires, because the server doesn’t track it. To force a logout early you need extra work, like a blocklist or short expiry times, which adds back some of the state JWT was trying to avoid.
  • “Storing the token anywhere is fine.” It’s not. If you stash a JWT somewhere a malicious script can read, an attacker can steal it and become you. How you store it matters, and a stolen token is as good as a stolen password.

🛠️ Design Challenge

Try this one on your own to test yourself.

You’re designing login for an app with two parts: a normal website and a mobile app, both talking to the same backend. Think through these questions:

  • Which method fits the website, and which fits the mobile app? Why?
  • If a user reports their account was hacked and you need to log them out everywhere right now, which method makes that easy, and what would you have to add to the other one?
  • If your traffic grows and you add ten more servers, which method needs the least extra setup?

Write down your choices and your reasons. This is exactly the kind of trade-off thinking an interviewer wants to see.

🧩 What You’ve Learned

You can now explain how login state survives across requests, and the two main ways to keep it. Here’s what you’ve picked up:

  • ✅ HTTP is stateless, so the server forgets you between requests, and we add auth to remember you.
  • ✅ A session stores your state on the server and gives the browser a session id inside a cookie.
  • ✅ A JWT is a signed token holding your info, so the server verifies the signature instead of storing anything.
  • ✅ A JWT is signed, not encrypted, so the payload is readable and must never hold secrets.
  • ✅ Sessions are stateful and easy to revoke; JWTs are stateless and scale easily but are hard to revoke early.
  • ✅ Sessions are a great default for web apps, while JWTs shine for APIs and microservices.

Check Your Knowledge

Test what you learned. Pick an answer for each question, then click Check.

  1. 1

    Why do we need sessions or JWT to keep a user logged in?

    Why: HTTP treats each request as fresh with no memory, so we add sessions or JWT to carry identity across requests.

  2. 2

    With session-based auth, what does the cookie actually hold?

    Why: The cookie holds only a random id like a ticket; the real login data stays on the server.

  3. 3

    Is the payload of a JWT hidden from whoever holds the token?

    Why: A JWT is signed, not encrypted, so the payload is readable and you must never put secrets in it.

  4. 4

    Why is logging a user out early harder with JWT than with sessions?

    Why: Sessions can be deleted instantly on the server, but a stateless JWT needs extra work like a blocklist or short expiry to revoke early.

🚀 What’s Next?

You now know how a site keeps you logged in. Next, let’s build on the security picture.

Get these down and you’ll have a solid grip on the security basics every backend and system design interview leans on.

Share & Connect