Unit 3 · Scripting & Storage

Lesson · Unit 3 · 8 min read

Cookies, sessions & storage, where web data lives between requests.

HTTP is stateless — every request is its own thing. To know who's logged in or what's in their cart, you need somewhere to keep state. Five options, each with a different shape.

Section · 01

HTTP is stateless — and why that's a problem

Each HTTP request is independent. The server doesn’t remember you between requests. So how does a logged-in user stay logged in? How does a cart survive a refresh? With one of five storage mechanisms.

Cookies         — small key/value pairs sent on every request to a domain
Sessions        — server-side state identified by a session-id cookie
localStorage    — bigger blob, JS-only, persists forever
sessionStorage  — same, but cleared when the tab closes
IndexedDB       — full client-side database for structured data

Section · 02

Cookies — small, automatic, persistent

A cookie is a small (~4KB) key/value pair the server sets on a response. The browser stores it and automatically sends it back on every subsequent request to that domain.

HTTP response:
  Set-Cookie: session_id=abc123; Max-Age=3600; HttpOnly; Secure; SameSite=Lax; Path=/

HTTP request (next visit, automatic):
  Cookie: session_id=abc123

The flags that matter

HttpOnly        — JavaScript can't read this cookie (defeats XSS theft)
Secure          — only send over HTTPS
SameSite=Lax    — don't send on cross-site requests (defeats CSRF for most cases)
Max-Age=3600    — expires in 3600 seconds; without this, expires when tab closes
Path=/          — which paths the cookie applies to

Every session cookie needs HttpOnly + Secure + SameSite. No exceptions. Three lines that prevent two entire classes of attack.

Section · 03

Sessions — cookies that point to server state

A session is the pattern of putting only an opaque session ID in the cookie and keeping the actual user data on the server (in memory, Redis, or a database).

Cookie         — only the session ID (a random opaque string)
                  Example: session_id=abc123_random_unguessable

Server-side    — a record keyed by that ID, containing:
                  - user_id
                  - permissions
                  - cart_id
                  - expires_at

Why use sessions instead of stuffing data into cookies directly? Cookies are sent on every request — so packing user state into them bloats every request. And client-side data can’t be trusted; server-side data can.

Stateless alternatives like JWT(JSON Web Tokens) put signed user data directly in a cookie or header. The server can verify the signature without a database lookup. Tradeoff: tokens can’t be revoked immediately (they stay valid until expiration).

Section · 04

localStorage — JS-readable, persistent

localStorage is a JavaScript-only key/value store that survives tabs, refreshes, and browser restarts. ~5-10MB depending on browser.

localStorage.setItem("theme", "dark");
localStorage.getItem("theme");          // "dark"
localStorage.removeItem("theme");

// JSON for objects
localStorage.setItem("user", JSON.stringify({ id: 1, name: "York" }));
const user = JSON.parse(localStorage.getItem("user"));

Use for: theme/preferences, draft form data, non-sensitive UI state. Neveruse for: auth tokens. localStorage is readable by any JavaScript on the page, including malicious code injected via XSS. Cookies with HttpOnly cannot be read by JavaScript at all — that’s why they’re the right place for session IDs.

Section · 05

sessionStorage — same API, smaller lifetime

sessionStorage.setItem("wizard-step", "3");
sessionStorage.getItem("wizard-step");
// All sessionStorage data is cleared when the tab closes.

Use sessionStorage when you want state to survive a refresh but not survive closing the tab — like a multi-step form wizard or a one-time onboarding flow.

Section · 06

IndexedDB — a database in the browser

IndexedDB is a real (NoSQL-ish) database built into the browser, with indexes, transactions, and the ability to store gigabytes. The API is awkward — most people use a wrapper like idb or Dexie.

When to reach for it: offline-first apps (PWAs), file editors that cache work in progress, anything where you need to keep meaningful amounts of structured data on the client. For 95% of web apps, you don’t need it.

Section · 07

Pick the right tool — a decision tree

Is it an auth token / session?
  YES → HttpOnly cookie. Always. (Or server-side session keyed by an HttpOnly cookie.)

Does the server need to see it on every request?
  YES → Cookie (with proper flags).
  NO  → next question.

Does it need to survive closing the tab?
  YES → localStorage.
  NO  → sessionStorage.

Is it structured data, queryable, possibly huge?
  YES → IndexedDB.

Is it sensitive in any way?
  YES → server, not browser. Don't even start.

Next lesson: the place server-side state actually lives — databases. Relational vs document, basic SQL, and the ORMs that put a nicer face on it.