DEV Community

137Foundry
137Foundry

Posted on

Understanding Cache Storage Strategies for Progressive Web Apps

The Cache Storage API is what makes service workers useful for offline support. It gives your service worker a programmable key-value store for HTTP request/response pairs, accessible across page loads and browser sessions. But the API itself is just a storage mechanism. The real design decision is the caching strategy: how do you decide when to serve from cache versus when to fetch from the network?

Getting this wrong produces bugs that are subtle and frustrating. Serving stale content to users who are online. Failing to load offline when you expected the app to work. Showing users data from last week because the cache invalidation logic never ran. Most service worker bugs trace back to a mismatch between the chosen strategy and what the content actually requires.

This piece covers what the Cache Storage API is, the five major caching strategies, when each is appropriate, and how to think about combining them in a real application.

What the Cache Storage API Actually Is

The Cache Storage API stores HTTP request/response pairs under named cache objects. Unlike localStorage or sessionStorage, Cache Storage stores full HTTP responses -- including headers, status codes, and body -- not just serialized values. This makes it suitable for storing arbitrary web content, from HTML documents and JavaScript bundles to API responses and images.

Cache Storage only supports GET requests. POST responses and other non-GET requests cannot be cached through this API, which is an important constraint for offline write operations (those require IndexedDB and a background sync pattern).

The API is asynchronous throughout. Every operation -- opening a cache, matching a request, putting a response -- returns a Promise. This is important to keep in mind when writing fetch handlers: all cache interactions are async, and forgetting to await them is a common source of silent failures.

Multiple named caches can coexist on the same origin. A typical production pattern uses separate caches for different content types: "app-shell-v2" for precached static assets, "api-cache-v1" for API responses, "images-v1" for media. Separating caches by type makes selective invalidation straightforward -- you can clear the API cache and leave the app shell intact when rolling out a backend change.

The MDN Web Docs Cache Storage API reference covers the full API including caches.open(), caches.match(), caches.keys(), and cache.delete().

Strategy 1: Cache First

Cache First serves from cache and falls back to the network only when the cache misses. There is no network round-trip on cache hits, which makes it the fastest strategy for users.

Use Cache First for assets that are stable and versioned: JavaScript bundles, CSS files, fonts, icon sets, and other static assets whose URLs change when their content changes (content-hashed filenames). A cache hit on a content-hashed asset is always correct because the URL itself encodes the version.

The risk with Cache First is staleness. If you cache an asset under a non-versioned URL (like /styles/main.css), the cache will serve the old version until it is explicitly cleared. This is why Cache First pairs well with content-hashed asset URLs and poorly with mutable URLs.

Cache First is also appropriate for images and other media uploaded by users. Once uploaded, an image at a given URL does not change. Caching it means subsequent loads are instant without consuming bandwidth.

Strategy 2: Network First

Network First attempts the network and falls back to cache if the network fails. Users who are online always get fresh content. Users who are offline get whatever is in cache.

Use Network First for content that changes frequently and where freshness is important: API responses, user feed content, real-time data, account information. The guarantee that online users always get fresh content is the primary benefit.

The tradeoff is latency. Every request incurs a network round-trip when the user is online. On slow connections -- a user on 3G or poor hotel wifi -- this makes the app feel slow even though the offline fallback works correctly. The solution is a network timeout: if the network does not respond within N milliseconds, serve from cache and revalidate in the background. Workbox's NetworkFirst strategy supports networkTimeoutSeconds for this purpose.

Network First with a timeout gives you most of the freshness guarantee of pure Network First while eliminating the worst case of waiting indefinitely on a slow or unreliable connection.

Strategy 3: Stale While Revalidate

Stale While Revalidate serves from cache immediately, then updates the cache in the background by fetching from the network. The user always gets an instant response (from cache). The cache is continuously refreshed so that subsequent visits get fresh content.

This strategy is well-suited for content where a slightly stale version is acceptable: profile data, settings, category pages, blog listings, documentation. The user experience is consistently fast -- no spinners, no waiting -- and the data is typically fresh enough within a visit or two of each update.

Stale While Revalidate is often the best default for content that does not fit neatly into either Cache First (too mutable) or Network First (too latency-sensitive). It threads the needle between performance and freshness for most content that sits in the middle of that spectrum.

Strategy 4: Network Only

Network Only does not interact with the cache at all. Requests go directly to the network and fail if the network is unavailable.

Use Network Only for requests where caching would be incorrect or harmful: form POST requests, payment processing, analytics events, API calls with side effects. Since Cache Storage only supports GET requests, non-GET requests are automatically treated as Network Only -- this strategy is explicit handling for GET requests that should also bypass the cache.

Strategy 5: Cache Only

Cache Only serves from cache and never falls back to the network. Responses come only from what was explicitly cached during the install phase.

Use Cache Only sparingly: for assets that are precached and should never vary between service worker installs, or in strict offline scenarios where you want to guarantee no network requests. The risk is that a cache miss returns nothing, which is a worse outcome than a network failure. Only use Cache Only when you can guarantee the cache will be populated with exactly the content needed.

Combining Strategies in Practice

Production applications use different strategies for different URL patterns. A news application might use Cache First for JavaScript bundles, Network First with a timeout for article content, Stale While Revalidate for user preferences, and Cache Only for the offline fallback page.

Workbox, Google's service worker library, implements all five strategies and lets you map them to URL patterns declaratively using runtimeCaching configuration. The web.dev documentation on caching strategies includes decision guides for which strategy fits each content type.

Cache Size and Browser Storage Limits

Browsers impose storage quotas that vary by browser and available disk space. The Storage Manager API lets you check your current quota and usage. Cache Storage is included in the site's total storage budget.

When storage fills up, browsers may evict caches starting with the least recently accessed. To request persistent storage -- preventing eviction -- use navigator.storage.persist(). The user may be prompted to approve the request.

For a complete implementation guide covering service worker setup, offline fallback pages, and background sync, see the article on how to add offline support to a Progressive Web App on the 137Foundry blog.

137Foundry's web development services incorporate PWA caching architecture into client projects. Browser support for Cache Storage is tracked at caniuse.com. The W3C specification defines the formal API behavior for both the Cache Storage API and service workers. Visit 137Foundry to discuss PWA implementation for your application.

Top comments (0)