Two cache layers, one request path
Modern browsers check two separate caches before a resource request ever reaches the network. A service worker cache sits in front, followed by the HTTP cache (also called the browser cache). Only when both miss does the request go server-side.
These two layers serve the same broad purpose but behave very differently. The HTTP cache is automatic: the browser stores responses based on server-provided headers and respects their expiration. The service worker cache is programmable: your code decides what gets stored, when it gets served, and when it gets refreshed.
What the service worker layer adds
Service worker caching gives you fine-grained control that the HTTP cache cannot offer. You intercept requests with a fetch event handler and apply a strategy such as Cache-First or Stale-While-Revalidate. Workbox simplifies this routing; for example, you can register URL paths with a single line of regular expression code.
Common service worker strategies map to different use cases:
- Cache First: Serve from cache, fall back to the network. Best for long-lived, versioned assets.
- Stale-While-Revalidate: Serve the cached copy immediately, then update the cache in the background. Good for content that can tolerate brief staleness.
- Network First: Prefer the network, fall back to cache when offline or on flaky connections.
- Cache Only: Serve exclusively from cache, enabling full offline experiences.
Beyond strategy choice, the service worker layer brings two structural advantages. First, origins generally get more storage and greater persistence than the HTTP cache, which the browser can evict at any time — including when a user clears site data or hard-reloads. Second, the service worker cache remains usable when the network is unstable, while the HTTP cache is effectively useless offline because it cannot be consulted without a network round trip.
What the HTTP layer still does
The HTTP cache operates on a simpler model. Your server sets response headers that declare how long a resource should be cached. The browser honors that TTL automatically, with no scripting involved.
That simplicity is also a limitation. With HTTP caching you only get time-based expiry; there is no room for logic about network conditions, user state, or partial responses.
Matching expiry logic across both layers
One design option is to give the service worker cache and the HTTP cache the same expiry window. That approach has predictable failure modes depending on the length of the window.
Long expiry, same on both layers
With a 30-day expiry on both layers, the service worker serves the cached copy directly until it expires. At that point it requests the resource from the network, but the HTTP cache has already expired too, so the request goes all the way to the server. The HTTP cache provides no value in this scenario — it is always expired by the time the service worker needs it.
Medium expiry with revalidation
Consider a one-day expiry used by both layers with a Stale-While-Revalidate strategy. While unexpired, the service worker serves the cached resource and initiates a background revalidation, and the HTTP cache supplies the copy for that revalidation — avoiding a server hit. Once the one-day mark passes, the HTTP cache is also stale, so the revalidation must fetch server-side. The service worker gains little from the HTTP layer unless you add extra cache-busting logic to force fresh revalidation requests.
Short expiry with network preference
With a 10-minute expiry and a Network-First strategy, the service worker reaches for the network on every request. While the HTTP entry is fresh, the browser serves it without touching the server. After expiry, the request propagates to the server. To get consistently fresh responses in this pattern, you again need cache-busting to bypass the HTTP cache.
Across all three scenarios, the service worker cache remains an asset when network conditions degrade — the HTTP cache cannot serve anything in that state. But when the expiry windows are identical, the HTTP layer rarely contributes meaningfully to performance or freshness.
Using different expiry windows
The alternative is to let each layer expire on its own schedule. Giving the service worker a much longer window than the HTTP cache is generally the more useful arrangement.
Long service worker expiry
If the service worker cache expires at 90 days, users get instant responses for the entire window. The service worker decides exactly when to request fresh copies. The tradeoff is that you must define and maintain a deliberate caching strategy; there is no auto-pilot.
Medium service worker expiry with revalidation
With a 30-day service worker window and background revalidation, users still see instant responses, and the next request after expiry fetches fresh content automatically. Again, a well-designed strategy is required to make this behavior deliberate rather than accidental.
Short expiry with network preference
When the service worker expires content after one day and prefers the network, fresh requests hit the HTTP cache first. If the network drops, the service worker can still fall back to its own cached copy. The complication returns, though: network-first requests need extra cache-busting to bypass the HTTP cache when you specifically want to check the server.
Practical guidance
There is no single caching rule that fits every resource. The tradeoffs above suggest a few principles worth applying:
- Do not force the service worker expiry logic to match the HTTP cache. A longer service worker window gives you more control over when users receive fresh content.
- Treat the HTTP cache as a useful accelerator, not a reliable fallback. It cannot help when the network is down.
- Evaluate each resource type separately. Make sure your service worker strategy adds value rather than merely duplicating — or conflicting with — the HTTP cache behavior.
Related resources
For a deeper dive into the topics covered here, the following resources are worth reviewing:



