How the Browser Stores State
HTTP itself has no memory — every request to a server is, by design, completely independent of the last. Everything that makes a website feel "stateful" (staying logged in, remembering a shopping cart, keeping a dark-mode preference) depends on the browser storing something locally between requests. There are four main ways it does this, and this chapter is about understanding which tool fits which job — a distinction that gets directly relevant in later chapters covering cookie attributes, tracking prevention, and the real browser warning that prompted this course.
The Four Storage Mechanisms
Seeing Each One in Practice
Cookies — set via JavaScript or an HTTP response header
document.cookie = "theme=dark; path=/; max-age=2592000";
// Or set by the server in an HTTP response header (more common in practice):
Set-Cookie: theme=dark; Path=/; Max-Age=2592000
localStorage and sessionStorage — JavaScript only
localStorage.getItem('theme'); // "dark"
sessionStorage.setItem('formDraft', 'unsaved comment text...');
// Gone the moment this tab closes
IndexedDB — a real, asynchronous database API
request.onsuccess = (event) => {
const db = event.target.result;
// transactions, object stores, indexes — a real database, in the browser
};
Side-by-Side Comparison
| Property | Cookies | localStorage | sessionStorage | IndexedDB |
|---|---|---|---|---|
| Sent to server automatically? | Yes, every request | No | No | No |
| Accessible via JavaScript? | Yes, unless HttpOnly | Yes | Yes | Yes |
| Typical size limit | ~4KB per cookie | ~5–10MB | ~5–10MB | Hundreds of MB+ (browser-dependent) |
| Persists after tab closes? | Until expiry, if set | Yes, indefinitely | No | Yes, indefinitely |
| Data structure | Simple strings | Key-value strings | Key-value strings | Structured objects, indexed |
| API style | document.cookie / headers | Synchronous | Synchronous | Asynchronous |
Choosing the Right One
| Need | Use |
|---|---|
| The server needs to know this value on every request (e.g. a session ID) | Cookies |
| A user preference that should persist across visits, purely client-side (e.g. dark mode) | localStorage |
| Temporary state that shouldn't survive closing the tab (e.g. a multi-step form's draft) | sessionStorage |
| A genuinely large or structured dataset the app needs offline (e.g. cached articles, an offline-capable app's data) | IndexedDB |
Looking Ahead in This Course
This comparison sets up everything that follows: Chapter 2 goes deep into cookie attributes specifically (since cookies are the most complex of the four, with real security implications). Chapter 3 covers first-party vs third-party cookies, and Chapter 4 finally explains the actual mechanism behind the real browser warning that prompted this course — "the state of osztromok.com was recently purged because it was detected as a bounce tracker."
Chapter 1 Quick Reference
- Cookies — the only one automatically sent to the server; small (~4KB); accessible via JS unless HttpOnly
- localStorage — JS-only, persists indefinitely, ~5-10MB, simple key-value strings
- sessionStorage — same API as localStorage, but cleared when the tab closes
- IndexedDB — a real async database in the browser; large capacity, structured data
- Rule of thumb: server needs it → cookie; client-only preference → localStorage; tab-scoped draft → sessionStorage; large/structured offline data → IndexedDB
- Next chapter: cookies in depth — Domain, Path, Expires, Secure, HttpOnly, SameSite