In the browser, there are several types of storage mechanisms available for frontend applications. Each serves different purposes and comes with its own capabilities, lifespans, and security considerations.
🗂️ Browser Storage Types (Overview)
Storage Type | Size Limit | Persistent? | Accessible From | Auto Expiry |
---|---|---|---|---|
localStorage | ~5–10 MB | ✅ Yes | Any script on the same origin | ❌ No (manual clear only) |
sessionStorage | ~5 MB | ❌ No | Same tab only | ✅ When tab closes |
cookies | ~4 KB | ✅ Optional | Sent with each HTTP request | ✅ Optional (expiry based) |
IndexedDB | ~50–100 MB | ✅ Yes | Same origin | ❌ No |
WebSQL (Deprecated) | — | — | — | — |
✅ 1. localStorage
🟢 Use When:
- You need to persist non-sensitive user preferences or cached data.
- Data should remain after browser/tab is closed.
🔧 Example:
// Save user theme preference
localStorage.setItem('theme', 'dark');
// Retrieve it
const theme = localStorage.getItem('theme');
// Remove it
localStorage.removeItem('theme');
⚠️ Security Warning:
- ❌ Not encrypted.
- ❌ Accessible via JavaScript — vulnerable to XSS attacks.
- ❌ Never store tokens, passwords, or PII.
✅ 2. sessionStorage
🟢 Use When:
- Data is only needed for a single tab session (e.g., form data, temp flags).
- Good for multi-tab isolation.
🔧 Example:
sessionStorage.setItem('draftNote', 'Hello world!');
const note = sessionStorage.getItem('draftNote');
⚠️ Like localStorage
, not secure for sensitive data.
✅ 3. Cookies
🟢 Use When:
- You need to persist small pieces of data (e.g., login tokens).
- You want to send data to the server automatically with every request.
🔧 Example:
document.cookie = "username=JohnDoe; path=/; max-age=86400"; // 1 day
⚠️ Be careful:
- Sent with every HTTP request — performance hit if overused.
Secure tokens must use:
Secure
(HTTPS only)HttpOnly
(not accessible via JS)SameSite=Strict
(CSRF protection)
✅ 4. IndexedDB
🟢 Use When:
You need to store large structured data, like:
- Offline web apps
- Caching API responses
- Storing media, files, or complex objects
🔧 Example (Using idb
wrapper library):
import { openDB } from 'idb';
const db = await openDB('notes-db', 1, {
upgrade(db) {
db.createObjectStore('notes');
}
});
await db.put('notes', 'Buy milk', 'note1');
const note = await db.get('notes', 'note1');
⚠️ Safe from XSS? Not by default. Same precautions as others apply.
🔒 Storing Sensitive Data – What NOT to Do
❌ DON'T Store | Where |
---|---|
Access tokens / JWTs | localStorage , sessionStorage |
Passwords or PII | Any client-side storage |
CSRF tokens | Cookies with HttpOnly flag preferred |
🛡️ Best Practices for Sensitive Data
✅ Use HttpOnly Cookies for tokens:
Set-Cookie: token=abc123; HttpOnly; Secure; SameSite=Strict
✅ Use HTTPS always ✅ Sanitize all user input to prevent XSS ✅ Regularly clear unused storage ✅ Prefer IndexedDB for large/structured data with service workers
🎯 Real-Life Use Case Scenarios
Feature | Storage | Why |
---|---|---|
Remember dark/light theme | localStorage | Persistent across tabs |
Retain form state in tab | sessionStorage | Cleared on tab close |
Offline caching of app data | IndexedDB | Can handle large structured data |
Auth token storage (securely) | HttpOnly Cookie | Not accessible from JS |
Remember last visited page | localStorage | Retained between sessions |