CPCODELAB
Express

Sessions vs JWT: Choosing an Auth Strategy

9 min read

Sessions vs JWT: Choosing an Auth Strategy

There are two dominant approaches to keeping a user logged in across HTTP requests: server-side sessions stored in a database or in-memory store, and stateless JWTs signed by the server and stored on the client.

Server-Side Sessions with express-session

js
const session = require("express-session");

app.use(session({
  secret: process.env.SESSION_SECRET,
  resave: false,
  saveUninitialized: false,
  cookie: {
    httpOnly: true,
    secure: process.env.NODE_ENV === "production",
    maxAge: 7 * 24 * 60 * 60 * 1000 // 7 days in ms
  }
}));

// After login, attach user info to the session
app.post("/login", async (req, res) => {
  // ... verify credentials ...
  req.session.userId = user.id;
  res.json({ ok: true });
});

// Protected route reads from session
app.get("/dashboard", (req, res) => {
  if (!req.session.userId) return res.status(401).json({ error: "Not authenticated" });
  res.json({ userId: req.session.userId });
});

Comparison

  • Sessions: easy to revoke (delete the record), require a shared store (Redis) for multi-server deployments, send only a small cookie
  • JWT: stateless so they scale horizontally without a shared store, but hard to revoke before expiry without a denylist
  • Use sessions when immediate revocation matters (banking, admin panels)
  • Use JWT when you need stateless horizontal scaling or cross-service auth (microservices)

Never store JWTs in localStorage — they are readable by any JavaScript on the page and vulnerable to XSS. Prefer HttpOnly cookies with the Secure and SameSite=Strict flags set.

Ready to test yourself?
Practice Express— quiz & coding exercises