Web Storage, Cookies & Persistence

Medium100% Free~25 mins#localstorage#sessionstorage#cookies#httponly#samesite#web-storage#browser-apis#security
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}
13
14const storage = new StorageMock();
15
16// 1. Storing object without serialization
17storage.setItem('user', { id: 1 });
18const rawUser = storage.getItem('user');
19
20// 2. Storing number and boolean
21storage.setItem('count', 42);
22storage.setItem('active', false);
23const countType = typeof storage.getItem('count');
24const activeVal = storage.getItem('active');
25
26// 3. Proper JSON serialization
27storage.setItem('session', JSON.stringify({ token: 'xyz' }));
28const parsedToken = JSON.parse(storage.getItem('session')).token;
29
30console.log(rawUser, countType, activeVal, parsedToken);
Predict Console Output
Interactive Challenge

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.

Call Stack (Top = Active)
Global Execution Context
Lexical Scope / Bindings
storage:StorageMock { store: Map(0) }
Console Stream
> [empty]

Deep Technical Breakdown

Client-Side Storage Architecture Matrix

Storage MechanismCapacityLifetimeScopeAccessible ByTransmission with HTTP Requests
localStorage~5-10 MBPersistent across browser restartsOrigin (proto+host+port)JavaScript onlyNo
sessionStorage~5 MBTab lifetime (cleared on tab close)Specific browser tabJavaScript onlyNo
Cookies~4 KBConfigurable (Expires/Max-Age)Domain & PathJS & Server (unless HttpOnly)Yes, automatically on every request
IndexedDB> 250 MBPersistentOriginJavaScript (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:

javascript
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:

  1. HttpOnly: Prohibits client-side scripts from reading document.cookie. This is the primary defense against token theft via Cross-Site Scripting (XSS).
  2. Secure: Instructs the browser to only transmit the cookie over encrypted HTTPS connections.
  3. 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 (requires Secure flag).

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 setItem or removeItem call!
  • 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)?