sessionStorage vs localStorage vs cookies
The Short Answer
All three are client-side storage mechanisms, but they differ in lifetime, scope, size limits, and whether data is sent to the server. localStorage persists until explicitly cleared, sessionStorage lasts only for the browser tab's lifetime, and cookies are sent with every HTTP request to the server and can have expiration dates. Choosing the right one depends on whether you need persistence, server access, or tab isolation.
localStorage
localStorage stores key-value pairs that persist indefinitely — they survive page refreshes, browser restarts, and even system reboots. Data is scoped to the origin (protocol + domain + port) and shared across all tabs and windows on that origin. It's the go-to for data that should persist between sessions.
// Store data — persists until explicitly removed
localStorage.setItem('theme', 'dark');
localStorage.setItem('user', JSON.stringify({ name: 'Alice', id: 42 }));
// Retrieve data
const theme = localStorage.getItem('theme'); // 'dark'
const user = JSON.parse(localStorage.getItem('user') ?? '{}');
// Remove specific item
localStorage.removeItem('theme');
// Clear everything for this origin
localStorage.clear();
// Storage limit: ~5-10MB per origin (varies by browser)
Good use cases for localStorage
- ✅User preferences (theme, language, sidebar state)
- ✅Cached data that should survive page refreshes
- ✅Draft content (unsaved form data, editor state)
- ✅Feature flags or A/B test assignments
sessionStorage
sessionStorage has the same API as localStorage, but data only lasts for the duration of the page session — when the tab or window is closed, the data is gone. Each tab gets its own isolated storage, even for the same origin. This makes it perfect for data that should be tab-specific and temporary.
// Store data — cleared when tab closes
sessionStorage.setItem('currentStep', '3');
sessionStorage.setItem('formDraft', JSON.stringify({ name: 'Bob' }));
// Same API as localStorage
const step = sessionStorage.getItem('currentStep'); // '3'
// Key difference: tab isolation
// Tab A: sessionStorage.setItem('cart', '[...]')
// Tab B: sessionStorage.getItem('cart') → null (different session)
// Storage limit: ~5-10MB per origin per tab
Good use cases for sessionStorage
- ✅Multi-step form wizard progress (per-tab)
- ✅One-time notifications that shouldn't reappear after refresh within the same session
- ✅Temporary authentication state during a single session
- ✅Shopping cart for a single browsing session
Cookies
Cookies are the oldest storage mechanism and the only one that's automatically sent to the server with every HTTP request. They have a much smaller size limit (~4KB), support expiration dates, and can be configured with security flags. Cookies are primarily for server-side concerns — authentication tokens, session IDs, and tracking.
// Set a cookie with expiration and security flags
document.cookie = [
'session_id=abc123',
'expires=Fri, 31 Dec 2025 23:59:59 GMT',
'path=/',
'Secure', // Only sent over HTTPS
'HttpOnly', // Not accessible via JavaScript (set by server)
'SameSite=Strict' // Not sent with cross-site requests
].join('; ');
// Reading cookies (awkward API — returns all as one string)
const allCookies = document.cookie; // "session_id=abc123; theme=dark"
// Parsing a specific cookie
function getCookie(name: string): string | null {
const match = document.cookie.match(
new RegExp(`(?:^|; )${name}=([^;]*)`)
);
return match ? decodeURIComponent(match[1]) : null;
}
// Delete a cookie (set expiration in the past)
document.cookie = 'session_id=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/';
Good use cases for cookies
- ✅Authentication tokens (session IDs, JWTs)
- ✅Server-side preferences that affect response (language, region)
- ✅CSRF tokens
- ✅Third-party tracking (though increasingly blocked)
Full Comparison
| Feature | localStorage | sessionStorage | Cookies |
|---|---|---|---|
| Lifetime | Until explicitly cleared | Until tab/window closes | Until expiration date (or session) |
| Size limit | ~5-10MB | ~5-10MB | ~4KB per cookie |
| Sent to server? | No | No | Yes — with every HTTP request |
| Scope | All tabs on same origin | Single tab only | All tabs on same origin + path |
| Accessible via JS? | Yes | Yes | Yes (unless HttpOnly) |
| API | Simple (getItem/setItem) | Simple (getItem/setItem) | Awkward string-based API |
| Security flags | None | None | Secure, HttpOnly, SameSite |
Security Considerations
Storage choice has direct security implications. The wrong choice can expose sensitive data to XSS attacks or leak tokens to third parties.
Storing auth tokens in localStorage
localStorage is accessible to any JavaScript running on the page. If your site has an XSS vulnerability, an attacker can steal tokens with `localStorage.getItem('token')`. There's no way to restrict access.
✅Store auth tokens in HttpOnly cookies — they're not accessible via JavaScript, so XSS can't steal them. Use SameSite=Strict to prevent CSRF.
Storing large data in cookies
Cookies are sent with every HTTP request to the server. Storing large amounts of data in cookies wastes bandwidth on every single request — even for static assets if the cookie path is `/`.
✅Use localStorage or sessionStorage for client-only data. Only put data in cookies that the server actually needs on every request.
Forgetting cookies are sent cross-origin by default
Without `SameSite` restrictions, cookies are sent with cross-origin requests — enabling CSRF attacks where a malicious site triggers authenticated actions on your behalf.
✅Always set `SameSite=Strict` or `SameSite=Lax` on sensitive cookies. Use CSRF tokens as an additional layer of defense.
Decision Framework
Use this mental model to pick the right storage mechanism for your use case.
- Does the server need this data on every request?
- Yes → Cookie (with HttpOnly + Secure + SameSite)
- No → localStorage or sessionStorage
- Should the data persist after the tab closes?
- Yes → localStorage
- No → sessionStorage
- Should the data be isolated per tab?
- Yes → sessionStorage
- No → localStorage
- Is it sensitive (auth tokens, session IDs)?
- Yes → HttpOnly cookie (not accessible to JS)
- No → localStorage or sessionStorage is fine
Why Interviewers Ask This
This question tests your understanding of browser storage APIs, their tradeoffs, and security implications. Interviewers want to see that you know when to use each mechanism, understand the security risks of storing sensitive data client-side, and can reason about data lifetime and scope. It's a practical question — every web app needs to store data somewhere, and the wrong choice leads to security vulnerabilities or poor UX.
Quick Revision Cheat Sheet
localStorage: Persistent, ~5-10MB, all tabs, not sent to server
sessionStorage: Tab lifetime only, ~5-10MB, isolated per tab
Cookies: Sent with every request, ~4KB, supports HttpOnly/Secure/SameSite
Auth tokens: HttpOnly cookies — never localStorage (XSS risk)
User preferences: localStorage — persists across sessions, no server needed