Skip to content

Concept in Performance

Service worker startup and fetch overhead

Published Updated

Widely available since 2018-04W3C draft

A stopped service worker must start before it can run a fetch handler. When that handler then goes to the network, startup and handler execution precede the network request; navigation preload can start the navigation request in parallel with worker startup (Service worker deployment, Chrome for Developers).

BCD records NavigationPreloadManager, the mitigation used on this page, from Chrome 59, Edge 18, Firefox 99, and Safari 15.4 (NavigationPreloadManager.json, MDN browser-compat-data).

Browsers stop service worker processes when they are inactive and start them when an event needs dispatch. A controlled navigation that reaches a fetch handler therefore waits for a stopped worker to start. A cache response can compensate for that cost; a pass-through handler that calls fetch(event.request) adds the worker path before the network work it still needs (Service worker deployment, Chrome for Developers).

Navigation Timing exposes workerStart, the point when the request begins to be handled by the worker. It is 0 when no service worker controls the page. Chrome DevTools labels the corresponding request phases ServiceWorker Preparation and Request to ServiceWorker in the Network panel’s Timing tab (Network features reference, Chrome for Developers).

Navigation preload applies to navigation requests. Once enabled on a registration, the browser can start the network request while the worker boots, and the handler reads that response through event.preloadResponse. It does not remove the execution cost of other handler logic and can waste a request when the handler responds from cache.

Measure startup on the page, then use preload only for network-backed navigations.

The fallback branch reports that this navigation has no service worker timing rather than subtracting the zero sentinel.

const [navigation] = performance.getEntriesByType('navigation');
if (!navigation || navigation.workerStart === 0) {
console.log('This navigation has no service worker timing.');
} else {
const beforeWorker = navigation.workerStart - navigation.startTime;
const workerToRequest = navigation.requestStart - navigation.workerStart;
console.table({ beforeWorker, workerToRequest });
}

Collect these fields on real devices. The deployment guidance says startup varies with device capability and CPU pressure, so a single development-machine value is not a general budget.

Overlapping startup with a navigation request

Section titled “Overlapping startup with a navigation request”

Enable preload during activation when the registration exposes it. The fetch handler uses the preloaded response and falls back to an ordinary fetch when preload is absent or produces no response.

self.addEventListener('activate', (event) => {
if (!('navigationPreload' in self.registration)) return;
event.waitUntil(self.registration.navigationPreload.enable());
});
self.addEventListener('fetch', (event) => {
if (event.request.mode !== 'navigate') return;
event.respondWith((async () => {
const preloaded = await event.preloadResponse;
if (preloaded) return preloaded;
return fetch(event.request);
})());
});

If navigations normally come from Cache Storage, compare the avoided network time with the unused preload request before enabling it.

Chrome 112 introduced the console warning for recognized no-op fetch handlers. The optimization that omits worker startup and event dispatch shipped in Chrome 115. The BCD support statement now describes NavigationPreloadManager, which is the API represented by the cited data file (Skip service worker no-op fetch handler, Chrome Status; NavigationPreloadManager.json, MDN browser-compat-data).

Specifications

SpecificationStatus
Service WorkersW3C draft
  • Legend
  • Yes
  • Partial
  • Flag
  • No
  • Unknown
Browser / PlatformSupportVersionsConfidenceSourceNotes
Chrome (Desktop)#Yes40highsource—
Chrome (Android)#Yes40highsource1
Edge (Desktop)#Yes17highsource—
Firefox (Desktop)#Yes44highsource—
Firefox (Android)#Yes44highsource2
Safari (macOS)#Yes11.1highsource—
Safari (iOS)#Yes11.3highsource3
Samsung Internet#Yes4.0highsource4
WebView (Android)#Yes40highsource5
  1. Derived by browser-compat-data mirroring from Chrome.
  2. Derived by browser-compat-data mirroring from Firefox.
  3. Derived by browser-compat-data mirroring from Safari.
  4. Derived by browser-compat-data mirroring from Chrome Android.
  5. Derived by browser-compat-data mirroring from Chrome Android.

Source data: /compatibility/service-worker.json · Global usage: 96 % (StatCounter 2026-09, CC BY-SA 4.0)

Source: spec · MDN · Last verified 2026-10-20 · Confidence: high (computed from sources)