Glossary

Definition

skipWaiting()

Short definition

self.skipWaiting() is called inside a service worker's install (or activate) handler to skip the normal waiting state and activate immediately, even while older pages controlled by a previous worker are still open. It is usually paired with clients.claim() so the new worker also starts controlling those pages right away.

Reviewed July 27, 2026

Typical usage: self.addEventListener("install", (event) => { self.skipWaiting(); event.waitUntil(precacheAssets()); });. Calling it unconditionally on every install means every deploy activates instantly for all open tabs, which trades update speed for a small risk of mismatched client/worker logic mid-session.

The safer alternative is to call skipWaiting() only in response to an explicit user action, such as clicking "Update now" on an in-app banner that listens for registration.waiting, giving users control over when the reload happens.

skipWaiting() only affects the transition from waiting to activating; it does not itself reload any open pages, so pages already loaded will keep running old JavaScript until they next navigate, even though the new worker is now in control of their fetch events.

Workbox's core module exposes a shorthand, workbox.core.skipWaiting() (or self.skipWaiting() directly with workbox-window's messageSkipWaiting()), which is the pattern most production Workbox configs use.

Related terms
waiting state (service worker)
A service worker enters the waiting state after install succeeds but before it can activate, because the browser only replaces an active worker once every page it currently controls has been closed or navigated away from. It stays here indefinitely until those pages close or the code forces the transition with skipWaiting().
clients.claim()
self.clients.claim() is called inside the activate event of a service worker to make it start controlling every open page on the origin right away, rather than the default behaviour where a page keeps being controlled by whatever worker was active when it first loaded until the next navigation.
Service worker update cycle
Browsers check a registered service worker's script for updates on every navigation to a page in scope, and at least every 24 hours in the background, by re-fetching the script URL and comparing it byte-for-byte against the currently installed version. Any difference — even a single changed character or comment — triggers a fresh install/waiting/activate cycle for a new worker instance.
Service worker registration
Registration happens when a page calls navigator.serviceWorker.register("/sw.js", { scope: "/app/" }). The scope option (defaulting to the directory the script is served from) determines which pages the worker is allowed to control — a worker at /sw.js served with no scope option can normally only control /*, but serving it with the Service-Worker-Allowed HTTP header lets it claim a scope above its own script location.
Cache Storage API
The Cache Storage API, exposed as the global caches object, lets a service worker (or page) store Request/Response pairs in named caches, e.g. caches.open("shell-v1").then((cache) => cache.put("/logo.png", response)). Unlike the HTTP cache, it is fully scriptable, has no automatic eviction schedule tied to headers, and persists until explicitly deleted or the storage quota is exceeded.
Cache-first strategy
Cache-first is a fetch-handling strategy: event.respondWith(caches.match(event.request).then((cached) => cached ?? fetch(event.request))). It serves cached content instantly and skips the network entirely when a match exists, making it ideal for versioned, immutable assets such as hashed JS/CSS bundles or app-shell icons that never change once deployed.