A service worker that caches resources without versioning accumulates stale content indefinitely. When you ship a bug fix or critical update, users with a running service worker continue receiving the broken cached version — potentially for weeks, until they manually clear their cache or the browser evicts it. The cache name must change on each deploy, and the activate event must delete old caches. ISO 25010:2011 time-behaviour flags cache effectiveness; the operational risk is users being stuck on outdated or broken application versions with no server-side way to force an update.
High because unversioned service worker caches leave users running stale application code after deploys, with no server-side mechanism to force a refresh without manual cache clearing.
Include a version string or content hash in every cache name and delete all prior cache versions in the service worker's activate event.
// public/service-worker.js
const CACHE_NAME = 'app-cache-v2.1.0' // bump on each deploy
self.addEventListener('activate', (event) => {
event.waitUntil(
caches.keys().then((keys) =>
Promise.all(
keys.filter((key) => key !== CACHE_NAME).map((key) => caches.delete(key))
)
)
)
})
ID: performance-deep-dive.caching-cdn.service-worker-cache-versioning
Severity: high
What to look for: Count all service worker files. Enumerate cache versioning strategies: version strings, content hashes in cache names, and cleanup handlers. Check for a service worker file (public/service-worker.js, app/service-worker.js, or equivalent). Look for cache versioning (e.g., a version string or hash in the cache name). Verify that on new deploys, the cache version changes and old caches are cleaned up via caches.delete().
Pass criteria: A service worker is implemented. Cache keys include a version string or hash. The service worker deletes old caches on activation (in the activate event). New deploys update the cache version, triggering cleanup. At least 1 version string or hash-based cache name must be present.
Fail criteria: No service worker implemented, or the service worker does not version caches or clean up old caches.
Skip (N/A) when: The project is a static site with no dynamic content or service worker needs.
Cross-reference: For broader cache-busting strategy, see the cache-busting-documented check.
Detail on fail: "No service worker found in project" or "Service worker caches with fixed name 'app-cache' — old cache never deleted, disk usage grows with each deploy"
Remediation: Implement a service worker with versioned caches that cleans up old versions on activation.
// public/service-worker.js — versioned cache with cleanup
const CACHE_VERSION = 'v2.0.0'
self.addEventListener('activate', (e) => e.waitUntil(caches.keys().then(keys => Promise.all(keys.filter(k => k !== CACHE_VERSION).map(k => caches.delete(k))))))