Build1 distinct publisher3 min readUpdated
A fetch fired as the page goes away has no delivery guarantee, and your dev machine is exactly the place where it works anyway. sendBeacon and visibilitychange are the parts that survive production.
The Engineer · Build desk
Compiled by The EngineerSomething wrong?How this is made
The failure hides for a mechanical reason: the conditions that break it are the conditions you do not have locally. According to the dev.to write-up, a request fired during unload is sometimes completed if the connection is already established, and sometimes cancelled outright, and you cannot rely on either behaviour [6]. On a laptop hitting a local endpoint the socket is warm and the round trip is nothing, so the request lands before teardown. In production the same code meets a cold connection and a browser that has already decided the document is finished [1].
The distinction that actually matters is ownership of the request. `beforeunload` runs synchronously as the page is about to be discarded, and anything asynchronous started inside it inherits no delivery guarantee [5]. `sendBeacon` hands the request to the browser, which queues it and delivers it after the page is gone [2]. The bill for that transfer is narrow ergonomics: POST only, minimal headers, no custom headers, no response body, and a single boolean telling you whether the browser accepted the payload for queueing [3][4]. Any telemetry scheme that authenticates or routes on a custom header does not survive the move as written.
`fetch` with `keepalive: true` is the near miss. It does tell the browser to outlive the page context, but the source puts the ceiling at 64 KB shared across all active keepalive requests, and notes reliability problems in older Safari [7]. A shared budget is not a per-request limit, so measuring one flush in isolation tells you nothing about whether it will fit when something else is holding the allowance. That is why the fallback branch in a feature-detection snippet is the weaker path, not merely the older one.
The delivery race is also the smaller of the two bugs. On mobile, and iOS Safari in particular, `beforeunload` does not fire reliably when the user switches apps, locks the phone, or gets backgrounded by the OS, so events gathered in that session vanish with no record [10]. `visibilitychange` to `hidden` fires on all of those, plus navigation away and loss of focus [11]. Hidden is not dead, though: the user can come back, so the queue-and-clear pattern is what keeps the next batch honest [13]. Batching also keeps you under the payload limit and costs fewer requests than one call per event [12].
Two details are easy to skip. `sendBeacon` takes the same `BodyInit` types `fetch` accepts for a body [8], and a bare JSON string goes out as `text/plain` unless you wrap it in a `Blob` with an explicit type, which strict backends will notice [9]. And availability is not the obstacle anyone still pretends it is: Chrome 39 and Firefox 31 shipped it in 2014, Safari 11.1 in 2018, and it carries a Baseline 2022 label [14], meaning all three engines had it four years before the designation [1]. In any currently supported browser the `else` branch of the detection check never executes [15]. The open question in most codebases is not whether the API exists, but whether the exit path was ever wired to an event that fires.
Follow any of these and your For You feed starts watching them — no settings page required.
Ranked by verification strength, evidence, and original report placement.
With feature detection in place, the fetch keepalive fallback branch never runs when targeting any currently supported browser.
An analytics flush written as a fetch call inside a beforeunload handler works in testing and silently fails in production, because the browser's unload policy cancels in-flight requests before they complete.
navigator.sendBeacon has the browser queue the request and deliver it even if the page unloads before the network round trip completes.
sendBeacon returns a boolean: true if the request was successfully queued, false if the browser declined it, typically because the payload exceeds the size limit. It returns no response body and is fire-and-forget.
sendBeacon always sends a POST, allows no custom headers, and goes out with minimal headers by default.
The beforeunload event fires synchronously when the page is about to be discarded, and asynchronous operations started inside it have no delivery guarantee.
Evidence-backed comparisons of source perspectives and observed adoption signals. Read the methodology
Which Builder, Operator, and Investor concerns the observed source mix emphasized—not a truth score.
Evidence, demonstrated adoption, hype gap, incentives, and confidence are assessed independently, each on its own current evidence. How these are measured.
Single-source but checkable platform behaviour
All claims come from one dev.to tutorial with no spec citation, browser documentation link or measurement. They are, however, concrete and independently verifiable web-platform assertions (sendBeacon queueing and boolean return, POST-only with no custom headers, text/plain default without a typed Blob, keepalive's 64 KB cap, visibilitychange 'hidden' coverage, Baseline 2022 versions), and the article demonstrates each with runnable code rather than assertion alone. The unquantified pieces — the sendBeacon size limit in bytes and how much data the beforeunload pattern actually loses — hold the score mid-range.
Platform availability broad; real-world usage undocumented
Adoption evidence here is about API availability rather than uptake: sendBeacon is reported Baseline 2022, shipped in Chrome 39 and Firefox 31 in 2014 and Safari 11.1 in 2018, so the recommended path needs no dependency and no polyfill in practice. What the cluster does not supply is any usage disclosure — no data on how many sites still flush via fetch in beforeunload, no deployment case study, no volume of events recovered by switching to sendBeacon plus visibilitychange. Availability is high, demonstrated practice is unmeasured.
Mechanism sound, 'guarantee' framing overstated
The technical direction is well aligned with the evidence, but the headline and lede promise more than the mechanism delivers: 'sendBeacon guarantees delivery' and 'one call, one guarantee' sit alongside the same article's admission that the call returns false when the browser declines an oversized payload, that the caller must retain the batch until queueing succeeds, and that the API is fire-and-forget with no response body — so delivery is never confirmable end to end. The failure side is likewise asserted rather than measured ('silently fails in production', events 'disappear without a trace'), with some browsers possibly completing an established connection. Modest positive gap, not a fabricated story.
Author audience-building, no vendor stake
The article closes with an explicit promotional block — GitHub follow/star, a Discord community, Instagram, LinkedIn and an email address for work and contract inquiries — plus an interactive demo and a nine-question quiz funnel, so there is a clear personal audience-and-lead-generation incentive shaping the confident, absolute framing. Offsetting that, the recommendation is to a royalty-free browser standard with no product, vendor, sponsor or paid tier attached, so there is no commercial stake in the technical conclusion itself.
Moderate: one publisher, low-controversy platform facts
Confidence is capped by structure — a single publisher, a single item, no corroborating spec or documentation source in the cluster, and no independent measurement of the described data loss. It is lifted by the low-controversy nature of the material: these are stable, long-standing browser behaviours demonstrated with code that a reader can verify directly, and the main soft spot is rhetorical (an absolute 'guarantee') rather than factual.
build
height:auto is animatable now, so your max-height ceiling is a bug you can delete1 distinct publisher
build
Pin `formats` before you take the next/image v4 bump1 distinct publisher
build
The .mp4 that was never H.264: how a healthy serving path hid a codec bug1 distinct publisher
security
CVE-2025-62593: A Ray Developer's Browser Is Now the Attack Surface1 distinct publisher
Distinct publishers with included, body-backed reporting in this cluster.
dev.to
1 article · August 21, 2026