Browser Storage — localStorage, Cookies and IndexedDB
IntermediateFour options with different lifetimes, sizes and security properties. The choice that matters most is where an auth token goes, and the answer is usually not localStorage.
Overview
localStorage is the one everybody reaches for: synchronous, simple, about 5MB, and it survives a browser restart. sessionStorage is the same but scoped to one tab. Cookies are small and are sent with every request to the origin, which is what makes them useful for authentication and annoying for anything else. IndexedDB is the real database — asynchronous, large, structured. The security point worth internalising early: anything in localStorage is readable by any JavaScript on the page, so a single XSS gives away every token stored there.
localStorage and sessionStorage
Same API, different lifetime. Both store strings only, and both can throw.
localStorage.setItem('theme', 'dark')
localStorage.getItem('theme') // 'dark', or null
localStorage.removeItem('theme')
// Objects must be serialised
localStorage.setItem('user', JSON.stringify(user))
const user = JSON.parse(localStorage.getItem('user') ?? 'null')
// It can throw — private mode, quota full, storage blocked
function safeSet(key, value) {
try { localStorage.setItem(key, JSON.stringify(value)) }
catch { /* quota or blocked — carry on without persisting */ }
}
// sessionStorage: identical API, cleared when the tab closes,
// and not shared between tabs even on the same site.
// Cross-tab sync comes free with the storage event:
window.addEventListener('storage', e => {
if (e.key === 'theme') applyTheme(e.newValue) // fires in OTHER tabs
})Cookies, and Where Tokens Belong
The security comparison that decides your auth design.
// localStorage: readable by ANY script on the page.
// One XSS -> the attacker has your token.
localStorage.setItem('token', jwt) // convenient, and exposed
// httpOnly cookie: not readable by JavaScript at all.
// Set by the server:
Set-Cookie: session=abc;
HttpOnly; // JS cannot read it — blocks XSS theft
Secure; // HTTPS only
SameSite=Lax; // blocks most CSRF
Max-Age=86400
// The trade-off:
// localStorage -> vulnerable to XSS, immune to CSRF, easy cross-origin
// httpOnly cookie -> immune to XSS theft, needs CSRF protection,
// needs credentials:'include' cross-origin
// For a browser app talking to your own API, httpOnly + SameSite
// is the stronger default.IndexedDB and the Cache API
When you need more than a few megabytes or want to query structured data offline.
// IndexedDB — async, large (hundreds of MB), indexed, transactional.
// The raw API is verbose; in practice use a wrapper such as idb.
import { openDB } from 'idb'
const db = await openDB('aicancode', 1, {
upgrade(db) {
const store = db.createObjectStore('submissions', { keyPath: 'id' })
store.createIndex('by-problem', 'problemId')
},
})
await db.put('submissions', submission)
await db.getAllFromIndex('submissions', 'by-problem', problemId)
// Cache API — for HTTP responses, used by service workers
const cache = await caches.open('v1')
await cache.addAll(['/offline.html', '/styles.css'])Key Points to Remember
- 1localStorage persists across restarts, sessionStorage clears with the tab, and both store strings only
- 2localStorage access can throw in private mode or when the quota is full — always wrap it in try/catch
- 3Anything in localStorage is readable by any script on the page, so one XSS exposes every stored token
- 4An httpOnly, Secure, SameSite cookie cannot be read by JavaScript, which is the stronger default for auth
- 5The storage event fires in other tabs, giving cross-tab sync for free; IndexedDB is the option for large structured data
Interview Questions
Sign in to ask AriaWhat is the difference between localStorage and sessionStorage?
Why is storing a JWT in localStorage considered risky, and what is the alternative?
How would you keep two open tabs of your app in sync when a setting changes?
Ask Aria about Browser Storage — localStorage, Cookies and IndexedDB
Your personal AI tutor — ask anything about this concept
Revision Status
Personal Notes
Sign in to save personal notes for this topic.
Discussion
Sign in to join the discussion.