Real-user monitoring is repeatedly invoked across this series as the ground truth; this is the article about building it honestly. The browser hands you excellent primitives, and every step between those primitives and a dashboard is a chance to manufacture fiction.
The primitives worth collecting
Navigation Timing gives the document lifecycle (TTFB through load); Resource Timing gives per-asset waterfalls including, with the right response header, timing for cross-origin CDN assets; Paint/LCP/INP/CLS observers give experience metrics; and server-timing headers can carry cache status and POP identity into the browser’s own record, joining edge truth to client truth in one beacon. Collect deltas, not timestamps, and ship via sendBeacon or fetch-with-keepalive on visibility change, not unload, that event is a ghost on mobile.
Attribution or noise
A latency number without dimensions is decoration. The attribution set that earns its bytes: coarse geography, network type when available, device class, navigation type (cold, warm, back-forward-cache), protocol, and cache status from server-timing. That set turns your p95 from a number into a diagnosis, and every cut in this series (per-region, per-protocol, per-cohort) assumes it exists.
The organizational trap outlasts the technical ones: RUM dashboards that nobody owns decay into wallpaper, while owned ones become the arbitration layer for every performance claim, internal or vendor. The working pattern gives the pipeline an owner, publishes a weekly percentile digest to the teams whose work moves the numbers, and wires the same data into CDN evaluations, so the trials this series recommends run on instrumentation you already trust. When a provider disputes your numbers, and eventually one will, the response is a methodology document, not a shrug, and writing that document is an afternoon that upgrades every future negotiation you will have.
The traps
Survivorship bias is the big one: sessions that abandon during slowness often never beacon, so naive RUM systematically flatters the tail; measure and report beacon-loss rates. Then the parade of small lies: back-forward-cache restores counted as page loads (near-zero times polluting the distribution), timing-allow-origin missing so CDN assets report opaque zeros, single-page-app route changes conflated with navigations, and bot traffic wearing user clothes. Each has a known fix; all of them ship broken in naive implementations.
In practice
Instrument core pages with the primitive set above, tag with the attribution set, sample deterministically at a rate your volume affords (retain all errors and worst-decile), and validate against a week of synthetic probes before trusting a single chart. Then freeze the definitions: RUM value comes from longitudinal comparability, and metric redefinitions silently reset your history.
We deploy this exact RUM design as an engagement deliverable, methodology document included, arguments pre-won.
