Glossary

Definition

fetch event (service worker)

Short definition

The fetch event fires in the service worker for every navigation, script, image or XHR request originating from a page it controls. Calling event.respondWith(promise) lets the worker substitute its own Response, most commonly by checking the Cache Storage API first and falling back to fetch() from the network.

Reviewed July 26, 2026

A cache-first example: self.addEventListener("fetch", (event) => { event.respondWith(caches.match(event.request).then((cached) => cached || fetch(event.request))); });, one of the simplest strategies and a reasonable default for versioned static assets.

If a fetch handler does not call event.respondWith(), the request proceeds to the network exactly as if no service worker were present — this is why registering a worker with no fetch listener has zero effect on network behaviour, only on lifecycle and push events.

The fetch event does not fire for cross-origin requests unless the request is same-origin or the response is opaque and explicitly requested with mode: "no-cors", and it never fires for requests from a page the worker does not yet control (the first load after registration is typically served straight from the network).

Choosing the right strategy per request type — cache-first for immutable hashed assets, network-first for API calls, stale-while-revalidate for things like avatars — is the core design decision of any service worker; see web.dev's offline cookbook: https://web.dev/articles/offline-cookbook.

Related terms
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.
Network-first strategy
Network-first is a fetch-handling strategy: event.respondWith(fetch(event.request).then((res) => { cache.put(event.request, res.clone()); return res; }).catch(() => caches.match(event.request))). It prioritises up-to-date data and only serves a cached copy if the network request fails outright, making it the standard choice for API calls and frequently changing pages.
Stale-while-revalidate
Stale-while-revalidate is a fetch-handling strategy that serves whatever is already in Cache Storage without waiting on the network, then kicks off a background fetch to refresh that cache entry for the next request. It gives cache-first speed with eventual freshness, at the cost of occasionally showing content that is one request-cycle out of date.
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().
skipWaiting()
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.
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.