Local Storage vs IndexedDB vs Cookies
Browsers give you several ways to store data. That is useful, but it also creates confusion. You might reach for `localStorage` because it is easy. You might use cookies because they feel familiar. You might avoid IndexedDB because it sounds heavy. The better approach is to understand what each tool is for. The common browser storage options solve different problems:
- cookies
- localStorage
- sessionStorage
- IndexedDB They are not interchangeable.
The Mental Model
Ask two questions before choosing browser storage:
- Does the server need this value on every request?
- How much structured data do I need to store? If the server needs the value automatically with requests, cookies may be involved. If the value is small client-side UI state, `localStorage` or `sessionStorage` may be enough. If the app needs larger structured offline data, IndexedDB is usually the better tool. Do not start with the API. Start with the data.
Cookies
Cookies are sent with HTTP requests to matching domains. That is their defining feature. They are commonly used for:
- sessions
- authentication flows
- server-readable preferences
- small request-related state Cookies are not a general-purpose client database. They are small and attached to requests, which means bad cookie usage can add unnecessary weight to every request. Security settings also matter:
- `HttpOnly`
- `Secure`
- `SameSite`
- expiration
- domain and path scope For authentication, cookies can be a good choice when configured carefully. For random UI data, they are usually the wrong tool.
localStorage
`localStorage` is a simple key-value store in the browser. Example:
localStorage.setItem("theme", "dark");
const theme = localStorage.getItem("theme");
It is useful for small pieces of client-side state:
- theme preference
- dismissed banner
- selected tab
- draft UI settings
- simple feature toggles The API is easy, but there are limits. `localStorage` stores strings. If you store objects, you need JSON:
localStorage.setItem("settings", JSON.stringify(settings));
Then parse it later:
const settings = JSON.parse(localStorage.getItem("settings") || "{}");
Do not store sensitive secrets in `localStorage`. JavaScript on the page can read it.
sessionStorage
`sessionStorage` is similar to `localStorage`, but it is scoped to the current browser tab session. It can be useful for temporary state:
- wizard progress
- unsaved form state
- tab-specific filters
- one-session UI choices When the tab is closed, the data goes away. This is useful when persistence across browser restarts would be surprising.
IndexedDB
IndexedDB is a browser database for larger structured data. It is useful for:
- offline apps
- cached API data
- large client-side datasets
- local-first tools
- queued writes
- structured records IndexedDB is more complex than `localStorage`, but it is much more capable. If you are building a serious offline-capable app, IndexedDB is usually the browser storage tool to learn. The raw API can be verbose, so many projects use a wrapper library. The important concept is that IndexedDB can store structured data at a scale where `localStorage` is no longer appropriate.
What Not to Store
Be careful with:
- access tokens
- private user data
- payment information
- sensitive business records
- anything you would not want exposed to page JavaScript Browser storage is not automatically safe just because it is local. If malicious JavaScript runs on the page, it may be able to read client-side storage depending on the storage type and security setup. For authentication, design deliberately. Do not casually put long-lived secrets in localStorage because it is convenient.
Common Mistakes
Mistake 1: Using localStorage for everything
`localStorage` is simple, but it is not a database. Use it for small client preferences, not large structured app state.
Mistake 2: Storing sensitive tokens carelessly
Storage choice affects security. Authentication deserves a real design, not a quick convenience decision.
Mistake 3: Forgetting server behavior
Cookies are sent to the server automatically. That is useful for sessions and wasteful for random client-only settings.
Where This Shows Up in Real Projects
Browser storage decisions show up in many frontend projects:
- dark mode setting
- auth session
- saved filters
- offline notes
- cached API responses
- extension settings
- local-first editor state Each case has different needs. A theme toggle does not need IndexedDB. An offline document editor probably does.
Key Takeaways
- Cookies are request-aware and useful for server-readable state.
- `localStorage` is simple client-side string storage.
- `sessionStorage` is temporary per-tab storage.
- IndexedDB is better for larger structured browser data.
- Do not store sensitive secrets casually in browser storage.
Choose storage based on data shape, lifetime, and security needs.
Related Articles
Building a Browser Extension With TypeScript
- Fetch API Error Handling in Frontend Apps
- TypeScript for Python Developers