Find the Web Cache That Kept the Old Bug Alive
R047 starts with a user seeing yesterday's JavaScript after you deployed the fix. R097 starts with an app still loading while the phone is offline. Same family, different owner. A browser cache, service worker, CDN, reverse proxy, and origin can all answer one request. "Clear your cache" does not tell you which one did.
This pack maps the full request path and gives each kind of response a deliberate cache policy.
Name the layer before changing it
Open the browser network panel and record:
- request URL and response status;
Cache-Control,Age,ETag,Last-Modified, and CDN cache headers;- whether the response says it came from a service worker;
- the current deploy or build ID;
- the script filename loaded by the HTML shell.
Then repeat with DevTools cache disabled, with the service worker bypassed, and from a clean browser profile. Each test removes one possible owner.
Use two policies, not one
Content-hashed static assets such as app.8d31c2.js can be cached for a year with
immutable. A changed file gets a changed URL, so the old response remains correct for its old
name.
The HTML shell should revalidate or have a short lifetime. It is the small document that points the browser at the new hashed assets. Long-cache the shell and you keep shipping references to an old build.
Live API data needs its own policy. Prices, balances, orders, and permissions should normally go to the network first or use explicit revalidation. Never put authenticated responses in a shared public cache.
Service workers need a release plan
A service worker can keep running after a new deployment. Test both states:
- a first-time visitor with no worker;
- an existing installation controlled by the previous worker.
Version named caches, remove only caches the new worker owns, and decide when the new worker takes control. For live data, use network-first with a clearly labeled offline fallback. For app shell assets that barely change, cache-first can be reasonable.
Offline is something you design. If the page shows a cached price, the UI should know it is stale and say when it was saved.
A deploy verification that catches stale users
- HTML returns the new build ID.
- HTML references only current content-hashed assets.
- Those assets return long-lived immutable headers.
- The previous service worker updates cleanly.
- Live API routes are absent from static precache lists.
- An offline test returns only the data you deliberately allowed.
- A rollback keeps the older referenced assets available long enough to load.
Claude can compare manifests, headers, and service-worker rules. Code and browser tests must prove which layer returned the bytes.
Run the starter locally
npm test
npm run validate
npm run sample
The safe starter validates fictional cache evidence and returns a reviewable plan. The included n8n workflow calls the Node service inside Docker Compose. It never purges a CDN or unregisters a real worker.