Cache API vs IndexedDB vs localStorage
Choosing the right storage mechanism
Section titled “Choosing the right storage mechanism”The browser offers three main client-side storage APIs for persistent data. They serve different purposes and complement each other — the key is picking the right one for each use case.
| Storage | Best for | Data type | Async? | Approximate size |
|---|---|---|---|---|
| Cache API | HTTP responses, static assets | Request/Response | Yes | Large (GBs possible) |
| IndexedDB | Structured app data, offline records | JS objects, blobs | Yes | Large (GBs possible) |
| localStorage | Tiny config strings, UI preferences | String only | No (synchronous) | ~5 MB |
Cache API
Section titled “Cache API”The Cache API stores Request/Response pairs. It is shaped like HTTP — the key is a URL (or Request object) and the value is a Response. This makes it ideal for:
- Pre-caching static assets (HTML, CSS, JS, images) for offline use
- Runtime caching of API responses inside a Service Worker
- Serving stale content while a fresh version is fetched in the background
The Cache API is most useful in combination with a Service Worker. See the PWA course for Service Worker caching patterns.
IndexedDB
Section titled “IndexedDB”IndexedDB stores arbitrary JavaScript values (objects, arrays, blobs, typed arrays) in object stores with optional indexes. It is the right choice for:
- Offline app data: user records, messages, documents
- Large blobs: audio, video, images that are part of the app’s data model
- Data that needs to be queried, sorted, or filtered client-side
- Any structured data that does not fit the URL-keyed HTTP model
localStorage
Section titled “localStorage”localStorage stores string key/value pairs synchronously. It blocks the main thread on every read and write. Despite its convenience, it is only suitable for:
- Tiny preferences: theme choice, language, a single token
- Values read on every page load where the synchronous access is acceptable
- Anything under a few kilobytes
Never store large objects or do frequent writes in localStorage — it will stall rendering.
Decision diagram
Section titled “Decision diagram”flowchart TD
Q[What do you need to store?]
Q --> A{HTTP responses
or assets?}
A -->|Yes| CacheAPI[Cache API
caches.open / put / match]
A -->|No| B{Structured
app data?}
B -->|Yes| IDB[IndexedDB
object stores + indexes]
B -->|No| C{Tiny string
preference?}
C -->|Yes| LS[localStorage
setItem / getItem]
C -->|No| IDB