Skip to content
Foxipa

Suggest an edit

Tell us what should be corrected, clarified, or improved. Submission will be connected to Foxipa’s contribution service later.

No information is sent anywhere yet. Your suggestion is only prepared in your browser.

Learning

8.1 Workers and fetch(keepalive): the superset transport

The keepalive flag's specification, the fetch-groups exemption that lets requests outlive their context, and the exact capability trade against sendBeacon.

Levels: Advanced ~15 min read

Advanced

Workers cannot call sendBeacon — that fact is now old news in this series. What replaces it is not a compromise but a different tool with a wider handle and a weaker promise: fetch() with keepalive: true. This page reads the flag's actual specification, traces the mechanism that lets requests outlive their context, and inventories exactly what the superset gains and gives up.

The flag, in the spec's own words

"A request has an associated boolean keepalive. Unless stated otherwise it is false. This can be used to allow the request to outlive the environment settings object, e.g., navigator.sendBeacon() and the HTML img element use this." — Fetch, Requests

The mechanism behind those fourteen words sits in the fetch groups algorithm: when a group is terminated — the document discarded, the worker stopped — every in-flight request's controller is terminated unless its request's keepalive is true. That exemption is the entire survival trick, and it is the same one beacons rely on: a sendBeacon request and a hand-rolled fetch(keepalive) request are exempt from teardown by the same clause, draw from the same 64 KiB in-flight pool, and are indistinguishable to a service worker (as the detection page showed). The series' test suite verifies the worker side directly: inside a real dedicated worker, navigator.sendBeacon is undefined, fetch is present, and a fetch(keepalive) POST reaches a route-intercepted collector intact.

The superset advantages

The two keepalive transports compared; the last three rows are where decisions actually live.

Capability

sendBeacon

fetch(keepalive)

HTTP method

POST only, fixed

any method

Headers

none — Content-Type is derived

any headers via RequestInit

Response

never seen

full Response object

Credentials

forced include

omit / same-origin / include

Return signal

synchronous boolean

Promise

Flush on hidden

MUST, per the Beacon spec

not required by any spec

Shared 64 KiB pool

yes

yes — the same pool

Read the last three rows together and the shape of every later decision appears: the two transports differ in signal, guarantee, and synchrony — not in capacity. A hybrid that falls back from one to the other is choosing a different contract, not a different quota.

The sender recipe, with response handling

The runnable example is the reference sender for the superset side: one async function with the three RequestInit fields that matter, a result object mirroring the beacon's boolean shape (with status and body when available), and honest error routing — the stream-plus-keepalive TypeError surfaces synchronously from Request construction, while the quota refusal arrives later as a rejected promise. The injectable fetch lets the success path run under this page's network-blocking sandbox:

Interactive Runnable example
Edit

Ready to run.

Quick check

Inside a dedicated worker, which call can send telemetry that survives the worker's termination?

// inside a worker

Key takeaways

  • keepalive exempts a request from fetch-group termination — the survival mechanism beacons and keepalive fetches share.
  • Verified in the series' suite: a real worker has no sendBeacon, has fetch, and its keepalive POST arrives intact.
  • The superset: any method, any headers, a real Response, chosen credentials — at the cost of the MUST-flush guarantee and the sync boolean.
  • Error modes: stream bodies throw at Request construction; quota refusals reject the fetch promise with a TypeError.
  • Capacity is never the difference: both transports draw from the same 64 KiB in-flight pool.
Was this page helpful?

Mark this learning resource complete to track your learning progress.