Build1 publisher3 min readPublished
Moving the freeze watchdog into a Web Worker gets the report out of a dead tab
The dev.to writeup behind it argues for keeping every session on infrastructure you own, because a sampled replay tool captures a silent failure only by luck and click-based frustration signals never see scroll or drag.
The Engineer · Build desk

What happened
- A dev.to writeup describes a long-lived single-page app where a user's tab froze, every dashboard stayed green, and the session was missing from replay because it was sampled away and threw no error.
- The post puts the sampled fraction at 10 percent and says the number is illustrative, not any vendor's exact default.
- The proposed freeze watchdog runs in a Web Worker and sends its report from a snapshot the page handed over while the tab was still healthy.
Compiled by The EngineerSomething wrong?How this is made
Why it matters
- cost Full fidelity moves the storage bill from a vendor's sampling budget onto your own disk and ingest, which is why the post treats self-hosted infrastructure as the precondition for keeping every session.
- constraint A percentile dashboard cannot answer a named customer's email about yesterday, so aggregate health tells the on-call engineer nothing about whose tab locked up.
- decision Teams now choose between tuning sampling rules and retaining everything, and the post's position is that tuning cannot fix a capture path that depends on an exception being thrown.
- capability A permanent freeze that was previously knowable only from a support ticket becomes something the browser reports itself, from a thread that never stopped.
Session replay has two dependable capture paths [2]. One is a sampled slice of traffic. The other is any session where a JavaScript error fires [2]. The failures in the dev.to writeup fire nothing: a tab that degrades over hours, a scroll that stutters, a drag that lags, a main thread that stops answering [3].
So the sample is all that is left. The author uses 10 percent and says outright that the figure is illustrative, not any vendor's exact default [4]. Take it at face value and roughly nine complaints in ten arrive with nothing to watch back [5]. For that estimate to transfer, your plan's real sampling rate has to sit near 10 percent and your tool's replay cap has to be long enough to cover the whole session; the writeup gives about an hour as its cap, illustrative again [6]. An hour is plenty for a checkout flow and useless for a tab that has been open since Tuesday, where the part you want is the slow run-up before the freeze [6].
The second gap is the unit of measurement. Error monitors and APM tools are built around transactions: a page load, a route change, an API call, each bounded, each rolled into percentiles on a dashboard [7]. That shape came from servers, where a request arrives, does its work and leaves [7]. Percentiles cannot be traced back to one user [8].
The freeze detector is the part I would copy. A monitoring script inside the page runs on the same main thread that froze [9], so once the thread stops it cannot send anything. The watchdog instead lives in a Web Worker, survives the freeze, and posts the report itself from a snapshot the page handed over while the tab was still healthy [10]. The report is accurate as of that handoff, not as of the freeze [11]. The writeup also says to send the instant you know instead of batching [12], and batching is what would leave the payload queued on a thread that will not run again [19].
Frustration signals are the third gap. Rage-click and dead-click detection ship in current tools [18], and they detect frustration through clicks [13]. Scroll jank and sustained drag stutter produce no click, so each needs its own small detector that samples the gesture with timestamps [13]. That is two detectors you write and own.
Keeping every session means paying to store every session, which the author says is affordable only on infrastructure you already own [15], with the recorder assembled from tooling most teams have [16]. On sampling, the post is blunt: the fix "is not a cleverer sampling rule. It is full fidelity: keep every session" [17]. INP is not a substitute either. The writeup lists dead and rage clicks, scroll jank, drags and the merely-bad interaction as outside what INP measures, and argues that per-session logs match how people actually complain [14].
What to watch
- A published cost per stored session-hour for the self-hosted recorder would let teams price full-fidelity retention against their current replay bill.
- Vendors publishing real default sampling rates and replay caps would let you check the 90 percent miss estimate against your own plan.
- A scroll-jank or drag-stutter signal shipping in a mainstream RUM product would remove two of the detectors teams would otherwise write.