Web Storage, Cookies & Persistence
Key Learning Objectives
Compare the 4 primary browser persistence mechanisms: localStorage, sessionStorage, Cookies, and IndexedDB.
Understand Web Storage string coercion mechanics and why objects serialize to '[object Object]' without JSON.stringify.
Master cookie security attributes: HttpOnly (XSS defense), Secure (HTTPS only), and SameSite (CSRF defense).
Understand the cross-tab storage event and why it only triggers in other windows of the same origin.
Learn storage quotas, synchronous blocking trade-offs, and why sensitive tokens should never be stored in localStorage.
The Interview Problem
What is logged to the console when the following Web Storage operations execute, and how do implicit string coercion and serialization dictate stored types?
1class StorageMock {2 constructor() {3 this.store = new Map();4 }5 setItem(k, v) {6 this.store.set(String(k), String(v));7 }8 getItem(k) {9 const val = this.store.get(String(k));10 return val !== undefined ? val : null;11 }12}1314const storage = new StorageMock();1516// 1. Storing object without serialization17storage.setItem('user', { id: 1 });18const rawUser = storage.getItem('user');1920// 2. Storing number and boolean21storage.setItem('count', 42);22storage.setItem('active', false);23const countType = typeof storage.getItem('count');24const activeVal = storage.getItem('active');2526// 3. Proper JSON serialization27storage.setItem('session', JSON.stringify({ token: 'xyz' }));28const parsedToken = JSON.parse(storage.getItem('session')).token;2930console.log(rawUser, countType, activeVal, parsedToken);
Predict Console Output
Select the option that matches what standard ECMAScript prints to the console:
[object Object] string false xyz
{"id":1} number false xyz
[object Object] string boolean xyz
null string false null
V8 Engine Execution Trace
Step 1 of 5 (Line 14)StorageMock instance is created. Models the W3C Web Storage specification where keys and values are coerced to DOMString.
Deep Technical Breakdown
Client-Side Storage Architecture Matrix
| Storage Mechanism | Capacity | Lifetime | Scope | Accessible By | Transmission with HTTP Requests |
|---|---|---|---|---|---|
localStorage | ~5-10 MB | Persistent across browser restarts | Origin (proto+host+port) | JavaScript only | No |
sessionStorage | ~5 MB | Tab lifetime (cleared on tab close) | Specific browser tab | JavaScript only | No |
Cookies | ~4 KB | Configurable (Expires/Max-Age) | Domain & Path | JS & Server (unless HttpOnly) | Yes, automatically on every request |
IndexedDB | > 250 MB | Persistent | Origin | JavaScript (async) | No |
The localStorage String Coercion Trap
Web Storage only stores strings. When a non-string value is passed to setItem(key, value), the browser engine implicitly converts it to a string:
localStorage.setItem('auth', { authenticated: true });
localStorage.getItem('auth'); // Returns '[object Object]'!
localStorage.setItem('isLoggedIn', false);
const status = localStorage.getItem('isLoggedIn'); // Returns string 'false'
if (status) {
// BUG: In JavaScript, any non-empty string is TRUTHY!
console.log('User is logged in!'); // Fires even though value is 'false'!
}To safely store structured data, always use JSON.stringify() on write and JSON.parse() with a try...catch on read.
Cookie Security Attributes
Cookies are sent with every matching HTTP request, making them critical for authentication and vulnerable if misconfigured:
HttpOnly: Prohibits client-side scripts from readingdocument.cookie. This is the primary defense against token theft via Cross-Site Scripting (XSS).Secure: Instructs the browser to only transmit the cookie over encrypted HTTPS connections.SameSite: Controls whether cookies are sent on cross-site requests to defend against Cross-Site Request Forgery (CSRF):Strict: Never sent on cross-site requests (e.g. following an external link to your site).Lax(modern default): Sent on top-level GET navigations, but blocked on cross-site POST/fetch requests.None: Sent on all requests (requiresSecureflag).
The Cross-Tab storage Event
When localStorage is mutated, the browser dispatches a storage event on window:
- Critical Nuance: The event fires on all other tabs/windows sharing the same origin, but never in the tab that executed the
setItemorremoveItemcall! - This is commonly used in production to synchronize authentication logout across all open browser tabs.
Common Traps & Mistakes
Storing JWT access tokens or sensitive user credentials in `localStorage`. Any XSS script injection can instantly read and exfiltrate all `localStorage` data.
Checking boolean flags in storage with `if (localStorage.getItem('flag'))`. The return value is the string `'false'`, which is truthy.
Expecting `sessionStorage` to be shared between two separate browser tabs navigating to the same URL. `sessionStorage` is strictly scoped to an individual tab.
Assuming the `storage` event fires in the tab that mutated `localStorage`. It only fires in other concurrent tabs of the same origin.
FAANG Follow-Up Probes
Probe #1
How does the Web Storage synchronous blocking API impact main-thread performance when reading large JSON payloads (>5MB)?
Probe #2
What is the difference between sessionStorage behavior when opening a new tab manually versus window.open()?
Probe #3
How does the Cache API differ from IndexedDB for progressive web applications (PWAs)?
