Real user monitoring that links the browser to the backend

Your server says 200 ms and your user says the page took six seconds. Both can be true, and RUM is how you find out where the rest of the time went.

The numbers you are judged on

Core Web Vitals give a shared vocabulary for how a page feels. The thresholds below are the published ones, and the usual convention is to assess each at the 75th percentile of page loads.

Metric What it measures Good Needs work Poor
LCP (Largest Contentful Paint) When the main content appeared ≤ 2.5 s 2.5 s to 4 s > 4 s
INP (Interaction to Next Paint) How quickly the page responds to input ≤ 200 ms 200 ms to 500 ms > 500 ms
CLS (Cumulative Layout Shift) How much the layout moved unexpectedly ≤ 0.1 0.1 to 0.25 > 0.25

Wrentrix reports LCP, INP and CLS at p75, with a good, needs-work and poor split. The split matters because a p75 hides shape. As an example, two applications may both show a p75 LCP of 2.4 s. In one, 90% of loads are good and the rest are barely over the line. In the other, 76% are good and 20% are poor, which suggests a specific population having a very bad time, perhaps a branch office on a slow link or an old device fleet. Same headline value, different job. The guide on monitoring Core Web Vitals explains how each metric is produced and what typically drives it.

Why lab tests are not enough

A performance audit run from a developer laptop tells you what one machine saw on one connection. Real users bring real variety: older hardware, a busy mobile network, a corporate proxy, a browser with extensions, a tab left open for four hours that has grown its memory use. INP in particular depends on real interactions, so it can't be measured in a lab with no user clicking anything.

A synthetic probe gives you the opposite strength: consistent measurement around the clock, including when nobody is using the application. The two answer different questions. Synthetic asks "is it up and responding from here?" RUM asks "what did people actually get?"

From a slow click to a backend span

Most browser monitoring ends at the browser. The most useful thing Wrentrix does here is that it doesn't: every fetch is linked to its backend trace through traceparent.

The header is the W3C Trace Context format, the same one that services use between themselves:

traceparent: 00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01

The fields are version, trace ID, parent span ID and flags. Because the browser generates this header on an outgoing request, the backend continues the same trace. A slow interaction can be followed from the page into the distributed trace of the API behind it, and down to the method that used the time. The W3C Trace Context guide covers the format in depth.

The CORS detail that catches people out

traceparent is not a CORS-safelisted header. If your frontend calls an API on a different origin, adding this header turns requests into preflighted ones, and the API must allow it. If not, the browser blocks the request, and your monitoring has just broken the application.

Same-origin requests aren't affected. For cross-origin APIs, the preflight response has to include:

Access-Control-Allow-Headers: traceparent, content-type, authorization

List whichever headers your application really sends. Preflight requests also add a round trip when not cached, so consider Access-Control-Max-Age too. Roll this out on the API side first, confirm it in a test environment, and only then enable the browser side. Test every cross-origin API, including third-party ones you don't control, which may need to be left out of header propagation.

Rolling it out

The browser collector is lightweight, and is configured per application. Each application gets its own key and its own list of allowed origins. These belong together: a key shipped in browser JavaScript is visible to anyone who opens developer tools, so it cannot be treated as a secret. The allowed-origin list limits where the data is accepted from. It also doesn't stop someone from forging requests with a script outside a browser, since origin headers can be set by any non-browser client, so treat incoming RUM data as untrusted input, like anything else that arrives from the public internet.

Planning items for an on-premise RUM deployment:

The collection endpoint has to be reachable by your users. This is the point most often missed in an on-premise setup. Browsers send data to your Wrentrix installation, so for an intranet application this is easy. For a public website, you must expose a path through your reverse proxy or DMZ to the collector. Nothing goes to a third party, but your network team should know about the new inbound path and may want to rate-limit it.

Content Security Policy. If your site sets a CSP, the collection endpoint must be allowed in connect-src, and the location of the collector script in script-src. Self-hosting the script from your own origin is usually simplest.

Personal data. URLs often contain identifiers. Session timelines can show what a person did and when. Even when collected on your own hardware, this may be personal data under rules such as KVKK or GDPR. Tell your data protection team what you plan to collect, check whether notices or consent need updating, and read the data residency page. None of this is legal advice.

Route names. Single-page applications change views without a full page load. Wrentrix tracks SPA routes, and for readable reporting the route should be a pattern such as /accounts/:id, and not thousands of distinct URLs. Check how your router's paths appear after setup.

What to do with each signal

Slow LCP

Split the time up first. A large part of LCP may be the server's first byte, which is where the linked backend trace helps. Beyond that, look at render-blocking resources, large images, and fonts. A page with a slow first byte and a page with a slow hero image need different people to fix them.

Poor INP

Long tasks on the main thread are the most common cause: a big synchronous render, a heavy event handler, or third-party script. Note that an API call in progress does not by itself harm INP, if the UI paints some feedback first. A button that shows no response until its fetch returns feels slow to users, and the remedy is usually immediate visual feedback.

High CLS

Usually this comes from images without dimensions, late-loading banners, or injected content pushing the layout down. It is often specific to a route, so the per-route view narrows things down quickly.

JavaScript errors

Wrentrix groups JS errors, so one bug on 40,000 page views is one item with a count. Stack traces from minified bundles are hard to read, so ask us how source maps fit into your pipeline. Expect noise from browser extensions and old browsers, and focus first on groups which began after a release.

Session timelines

A session timeline shows pages, fetches and errors in the order that a user encountered them. It is especially useful for reports like "it just stopped working", where the sequence is the clue. In this invented example, a timeline shows a token refresh failing at 09:14, followed by three silent 401s, followed by a user clicking save repeatedly with nothing happening. No single metric would have told you that story.

What RUM won't tell you

  • It only sees users who got far enough to load the collector. If DNS, TLS or your front door fails, there may be no data at all. Use synthetic probes to cover that.
  • It only sees browsers. Native mobile apps and API clients are outside the scope of a browser collector. Native apps can send traces with an OpenTelemetry SDK where one exists for the platform. Ask us about mobile if it is important to you.
  • Content blockers and strict corporate policies may stop collection for some users.
  • Low-traffic internal applications produce noisy percentiles. A p75 from 30 page views isn't a stable number.

Frequently asked questions

What is a good LCP, INP and CLS score?

Good is LCP at or under 2.5 s, INP at or under 200 ms and CLS at or under 0.1, usually measured at the 75th percentile. Poor is LCP over 4 s, INP over 500 ms and CLS over 0.25. The range between them is "needs improvement", and Wrentrix shows the split as well as the percentile.

How does RUM connect to backend traces?

The browser collector adds a W3C traceparent header to fetch requests, and the backend continues that trace. You can go from a slow front-end request to the backend spans behind it. Cross-origin APIs must allow the header in their CORS configuration, or browsers will block those requests.

Does browser data go to a third party?

No. The browser sends data to your own Wrentrix installation, and nothing leaves for an outside service. For public websites, this means you need to expose a collection path through your own reverse proxy or DMZ.

Does RUM work with single-page applications?

Yes. SPA routes are tracked, so views that change without a full page load are still measured. Check how routes are grouped after setup, since URLs that contain identifiers are best viewed as one route pattern.

Is the RUM key a secret?

No. Anything shipped to a browser can be read by any visitor, so per-app keys identify an application and do not authenticate a user. Allowed-origin lists restrict where browsers can send from, and the endpoint should still be treated as receiving untrusted input.