What a service worker must never cache

A service worker sits between your application and the network, and answers when the network cannot. Everything depends on which responses it is allowed to keep.

The four strategies

  • Cache first. Serve from cache, go to the network only on a miss. For fonts, icons and compiled assets, which change only when you deploy.
  • Network first. Try the network, fall back to cache. For content pages, where a slightly stale page beats an error page.
  • Stale while revalidate. Serve the cached copy immediately, then fetch a fresh one in the background for next time. The fastest of the four, and the one whose trade-off is easiest to miss.
  • Network only. Never cache. For everything below.

A word on stale while revalidate

It feels instant because it never waits for the network. That is also its catch: the visitor always sees the previous version. Publish a correction and the first person to arrive still reads the mistake; they get the fix on their second visit, which they may never make.

It suits things where being one visit behind costs nothing: an avatar, a list of tags, a sidebar of recent items. It does not suit anything a reader might act on, and it is a poor fit for a page you will need to correct in a hurry.

If you use it, give yourself a way out: a versioned cache name you can bump on deployment turns « one visit behind » into « behind until the next release », which is at least a boundary you control.

What belongs in « never »

  • Anything with a price, a stock level or an availability.
  • Anything reflecting a permission. A page cached while an administrator was logged in, served later to somebody else, is a data leak with no attacker involved.
  • Anything with a personal name in it. Same reason.
  • Every non-idempotent request. POST, PUT, DELETE. Replaying one is not caching, it is acting twice.
  • Authentication responses. A cached login page with a stale token is a support ticket that takes three days to reproduce.

Version your cache, and clean up

Put a version in the cache name and delete the old ones on activate. Without that, every deployment leaves a full copy behind, and a user who visits once a month carries a year of dead assets.

Test the failure you will actually have

Switching the browser to offline is the easy case: requests fail immediately and your fallbacks fire. The interesting case is the slow, flaky connection where requests hang rather than fail, and a cache-first strategy quietly serves month-old data while the spinner turns.

Throttle rather than disconnect. That is where the bugs are.