
Turn real browser visits into actionable performance evidence before deployment
A page that feels fast on the developer’s machine can behave very differently when reached by another device over the public internet. In this guide, we build a privacy-conscious Real User Monitoring workflow, measure Core Web Vitals and navigation timing, and compare direct localhost visits with visits through a Localtonet HTTP tunnel. We also explain how to separate frontend rendering work from application response time, tunnel-path latency, and the visitor’s wider network conditions. The goal is not to produce one flattering speed score, but to collect repeatable evidence from real browsers.
📋 What's in this guide
Why measure real browser visits through a localhost tunnel?
Local development removes much of the path that a normal visitor must traverse. A browser connecting to localhost avoids a public internet route, remote relay, variable access network, and many of the device conditions that affect real users. The development computer may also have a fast processor, ample memory, a warm browser cache, and no competing mobile applications. A page can therefore look healthy locally while still delivering a poor experience on an ordinary phone or remote laptop.
Real User Monitoring, commonly shortened to RUM, records performance observations inside the browser that actually loaded and interacted with the page. This is different from a single synthetic test. A synthetic test is controlled and repeatable, which makes it useful for debugging and regression checks. RUM adds the distribution of experiences across actual devices, browsers, network conditions, routes, and user actions.
A Localtonet HTTP tunnel provides a practical intermediate testing stage. Our client establishes an outbound connection from the device that can reach the development service to a Localtonet relay server. The running tunnel provides a public address for the local application without requiring inbound router port forwarding, firewall changes, VPN setup, or a public IP address. The tunnel remains available only while the selected client or device is connected and the tunnel is running.
This public path lets a phone on mobile data, a remote teammate, or a controlled browser device reach the same local build. The resulting measurements are not a prediction of every future production deployment. They are observations of one specific architecture: a real browser, its current network, the public tunnel path, and the local development service behind it. That scope is still valuable when the experiment is labeled correctly.
The measured path includes the selected test device, its access network, the broader internet route, the Localtonet relay path, and the local application host. Results describe that test configuration. They should not be presented as a universal Localtonet latency figure or as a guarantee of future production performance.
Design a useful local-versus-tunneled experiment

Good performance testing begins before the instrumentation is installed. Decide what question the experiment should answer. “Is the site fast?” is too broad. Better questions include: “Does the initial dashboard route become slower when loaded through the public tunnel?”, “Do mobile visitors experience delayed rendering after the document arrives?”, or “Does an interaction remain responsive after the page loads?”
Define the two primary cohorts
At minimum, label each measurement as either a direct local visit or a tunneled visit. A direct local visit normally reaches a loopback address such as localhost or 127.0.0.1. A tunneled visit uses the public HTTPS address assigned to the running Localtonet HTTP tunnel.
Keep the application build, route, test data, and server process the same between cohorts. If one cohort uses a debug build with source maps and another uses an optimized build, the comparison will mix deployment changes with network-path changes. Likewise, comparing an empty account locally with a data-heavy account remotely does not isolate the tunnel path.
A same-device comparison is useful because it controls the CPU, browser, viewport, and much of the application state. First load the application directly, then load the same route through the tunnel. However, a same-device test is not representative of a genuinely remote visitor. Follow it with separate devices and networks once the instrumentation is working.
Choose repeatable journeys
Select a small set of meaningful routes and actions. A practical plan might include the landing page, an authenticated dashboard, a data-heavy detail view, and one interaction such as opening a panel or submitting a test form. Record the intended starting state for each journey, including whether the browser should have a warm or cold cache.
Test initial page loads separately from subsequent client-side navigations. Single-page applications may perform substantial work during their first landing page and then navigate faster after JavaScript, fonts, and route data have been cached. Combining both types of navigation into one bucket hides that architectural difference.
Decide which context is genuinely necessary
Useful segmentation fields include the route group, local or tunneled exposure, broad device class, viewport category, browser family, test scenario, and whether the cache was intentionally warm or cold. A coarse network label such as office Wi-Fi, home Wi-Fi, or mobile data can be entered by the tester.
Avoid collecting a complete URL because query strings can contain search terms, document identifiers, email addresses, or temporary credentials. Prefer a normalized route name such as dashboard or item-detail. Do not record form values, authorization headers, cookies, full IP addresses, or arbitrary user identifiers merely to investigate performance.
| Test cohort | What it controls | What it helps reveal |
|---|---|---|
| Same device, localhost | Browser, CPU, viewport, and local application | A low-network-overhead baseline for loading and rendering |
| Same device, tunnel address | Most client and application variables remain similar | The effect of using the public route on that device and connection |
| Remote laptop through tunnel | A realistic off-device visit | Internet-path behavior and desktop rendering outside the development host |
| Phone on mobile data through tunnel | A distinct device and access network | Combined effects of mobile hardware, radio conditions, and the public route |
| Repeated warm-cache visit | Previously downloaded reusable assets | Subsequent navigation and interaction behavior |
If the local sample uses a warm cache on a powerful desktop and the tunneled sample uses a cold cache on a mobile phone, their difference includes much more than the tunnel path. Use paired tests for isolation, then broader field samples for realism.
Add Core Web Vitals and navigation timing to the application

The current Core Web Vitals cover three different dimensions of user experience. Largest Contentful Paint, or LCP, represents loading performance. Cumulative Layout Shift, or CLS, represents visual stability. Interaction to Next Paint, or INP, represents interaction responsiveness. They answer different questions, so no single one should be treated as an overall speed score.
Browser timing data complements these metrics. The Navigation Timing API can show when the browser started the navigation, began requesting the document, received the first response byte, finished receiving the document, reached DOM milestones, and completed the load event. These boundaries help determine whether a poor LCP starts with a late document response or occurs after the document is already available.
Install a maintained Core Web Vitals implementation
For a JavaScript application using npm, install the maintained web-vitals package. Using a standards-aligned implementation is safer than recreating the complete metric algorithms from individual performance entries, particularly for INP and CLS.
npm install web-vitals
Other build systems should use the installation method supported by their package manager and current application framework. The example below assumes that the project can import ECMAScript modules. It sends compact JSON records to a same-origin endpoint named /rum. That endpoint is an application endpoint for this example, not a Localtonet endpoint. You must implement it in your own application or replace the path with your existing telemetry collector.
import { onCLS, onINP, onLCP } from 'web-vitals';
const RUM_ENDPOINT = '/rum';
function exposureType() {
const loopbackHosts = new Set(['localhost', '127.0.0.1', '::1']);
return loopbackHosts.has(window.location.hostname)
? 'local'
: 'tunnel';
}
function routeGroup() {
const path = window.location.pathname;
if (path === '/') return 'landing';
if (path.startsWith('/dashboard')) return 'dashboard';
if (path.startsWith('/items/')) return 'item-detail';
return 'other';
}
function viewportClass() {
if (window.innerWidth < 600) return 'small';
if (window.innerWidth < 1024) return 'medium';
return 'large';
}
function sendRum(record) {
const body = JSON.stringify({
schemaVersion: 1,
exposure: exposureType(),
route: routeGroup(),
viewport: viewportClass(),
recordedAt: new Date().toISOString(),
...record
});
const payload = new Blob([body], {
type: 'application/json'
});
if (!navigator.sendBeacon(RUM_ENDPOINT, payload)) {
fetch(RUM_ENDPOINT, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body,
keepalive: true,
credentials: 'same-origin'
}).catch(() => {
// Telemetry must never break the application experience.
});
}
}
function reportWebVital(metric) {
sendRum({
recordType: 'web-vital',
metric: metric.name,
value: metric.value,
delta: metric.delta,
rating: metric.rating,
metricId: metric.id,
navigationType: metric.navigationType
});
}
onLCP(reportWebVital);
onCLS(reportWebVital);
onINP(reportWebVital);
Adapt the route normalization rules to the application. The code intentionally records window.location.pathname only through a controlled mapping. It does not transmit query strings, fragments, page content, or the raw performance entry objects. Raw entries can carry more detail than a focused predeployment experiment needs.
The hostname-based label is suitable when the two cohorts are loopback and the public tunnel address. If local testing uses a LAN hostname, reverse proxy, container hostname, or another non-loopback address, replace this logic with an explicit test-mode value supplied by the application. Never silently put ambiguous observations into the local or tunnel bucket.
Capture Navigation Timing separately
Run the following code after the page load event. It reads the document navigation entry and records durations instead of transmitting the full entry. Durations may be zero or unavailable when a browser does not expose a phase, so the ingestion endpoint should accept nullable values and should not reinterpret a missing measurement as zero latency.
function roundDuration(value) {
return Number.isFinite(value)
? Math.max(0, Math.round(value))
: null;
}
function reportNavigationTiming() {
const navigation = performance.getEntriesByType('navigation')[0];
if (!navigation) return;
const tlsDuration =
navigation.secureConnectionStart > 0
? navigation.connectEnd - navigation.secureConnectionStart
: null;
sendRum({
recordType: 'navigation',
navigationType: navigation.type,
redirect: roundDuration(
navigation.redirectEnd - navigation.redirectStart
),
dns: roundDuration(
navigation.domainLookupEnd - navigation.domainLookupStart
),
connection: roundDuration(
navigation.connectEnd - navigation.connectStart
),
tls: tlsDuration === null
? null
: roundDuration(tlsDuration),
requestToFirstByte: roundDuration(
navigation.responseStart - navigation.requestStart
),
responseDownload: roundDuration(
navigation.responseEnd - navigation.responseStart
),
responseStartFromNavigation: roundDuration(
navigation.responseStart - navigation.startTime
),
domInteractive: roundDuration(
navigation.domInteractive - navigation.startTime
),
domContentLoaded: roundDuration(
navigation.domContentLoadedEventEnd - navigation.startTime
),
loadEvent: roundDuration(
navigation.loadEventEnd - navigation.startTime
),
transferSize: navigation.transferSize || null,
encodedBodySize: navigation.encodedBodySize || null,
decodedBodySize: navigation.decodedBodySize || null
});
}
window.addEventListener('load', () => {
window.setTimeout(reportNavigationTiming, 0);
});
The field named requestToFirstByte measures the interval from the browser starting the document request to receiving its first response byte. The responseStartFromNavigation field includes earlier navigation phases visible to the browser. Naming these fields precisely prevents analysts from treating two different intervals as if they were identical.
Your /rum endpoint should accept only the expected method and schema, enforce a small body limit, validate metric names and numeric ranges, and return a minimal success response such as an empty response. Apply the same authentication and authorization policy used by the test application. Telemetry must fail safely: a rejected beacon must not prevent the page from loading or responding to input.
Performance APIs, metric availability, beacon delivery, transfer-size fields, and network information vary by browser and browsing mode. Record missing values as missing. Do not replace them with invented measurements, and do not assume every beacon will arrive.
Build and verify the localhost baseline
Verify the instrumentation before introducing the tunnel. Start the local application using its normal documented development or test command, then open the intended loopback URL. The exact command and local port depend on the application, so this guide does not invent them. Confirm the values from the project’s configuration or startup output.
Check the collection path
- Open the browser developer tools and select the Network panel.
- Load a route included in the test plan.
- Confirm that the page itself succeeds before evaluating its timing.
- Look for a request to
/rumafter the page loads or a metric is finalized. - Verify that the server accepts the JSON and does not return an authentication, validation, or routing error.
- Inspect a stored record and confirm that its exposure label is
local. - Confirm that the route value is normalized and contains no query string or personal data.
Exercise at least one meaningful interaction so INP has an opportunity to observe user input. Merely opening the page and closing the tab may produce LCP and CLS information but no useful interaction measurement. Use the same interaction sequence planned for tunneled testing.
Separate cold and warm visits
A first visit often downloads more resources than a repeat visit. Record these states separately rather than alternating randomly and pooling everything together. For a controlled cold-cache run, use an isolated browser profile or the browser’s supported cache-clearing workflow. For a warm run, revisit the same route without clearing reusable resources.
Developer tools can alter performance, especially when recording detailed traces or applying throttling. Use them to validate instrumentation, then collect the comparison sample without heavy profiling panels open. If CPU or network throttling is enabled for a controlled test, label that cohort and apply the same setting to both paths.
Collect enough observations to see variation
Do not decide that a route is fast or slow from one load. Background compilation, garbage collection, browser extensions, local database work, cache state, and operating-system activity can affect a single visit. Collect repeated observations for each planned scenario and inspect the distribution.
The required sample size depends on the variability and the decision being made. A small predeployment test will not have the statistical power of large production telemetry. Report the count with every percentile, and treat the long tail cautiously when the sample is small. A P90 from ten observations is not a stable characterization of a broad user population.
Expose the application with a Localtonet HTTP tunnel
Once the localhost baseline works, create a Localtonet HTTP tunnel targeting the local IP address and port where the application is listening. The client must run on the same device or on a device that can reach that local target. Creating the configuration alone does not make it available. The selected device must be connected and the tunnel must be started.
HTTP tunnels can use the process types shown in the current dashboard, including a random subdomain, a custom subdomain where supported, or a custom domain. These options serve the application at a public HTTPS address. Custom-domain DNS instructions can change, so consult the current dashboard and documentation rather than copying unverified DNS values into a test plan.
Install and run the Localtonet client
Install the Localtonet application for the operating system on a device that can reach the development service. Start the client and keep it running for the duration of the test. Use the current download and installation guidance rather than an unverified command copied from an older environment.
Authenticate and select the test device
Use the device-specific authentication token associated with the client and select that device for the tunnel. Treat the token as a secret. Do not place it in application source code, browser telemetry, screenshots, test reports, or shared shell history.
Select an available relay server
Choose a currently available relay server or region in the dashboard. Availability can vary, so obtain the value from the current product rather than hardcoding a server code in the application or article instructions. Record the selected test region in private experiment notes if it is needed to reproduce the run.
Create the HTTP tunnel configuration
Select the HTTP tunnel workflow and point it to the local IP address and port used by the application. Choose the appropriate process type from the current dashboard. Verify the target carefully, especially when several development services are running on adjacent ports.
Start the tunnel and open its public address
Press Start, wait for the tunnel to run, and open the assigned public HTTPS address. Confirm that the same route, application build, test account, and data used for the local baseline are available. The tunnel is usable only while the selected client remains connected and the tunnel is running.
Stop or delete the tunnel after testing
When the measurement window is complete, stop the tunnel. Delete it if the configuration is no longer needed. Also disable temporary test accounts and remove test-only telemetry collection when those components have served their purpose.
For the current dashboard sequence and available options, consult our Localtonet HTTP tunnel documentation. The dashboard is the authority for current server choices and configuration values.
Do not assume that an unlisted or difficult-to-guess address is access control. Protect the application with authentication, use least-privilege test accounts, remove production secrets and personal data, and expose only the service required for the experiment. Do not place the RUM collector outside the application’s authorization boundary without a deliberate security review.
Compare local and tunneled visits without misleading yourself
Begin with paired runs on the same device. Use the same browser version, viewport, route, test data, cache state, and interaction sequence. Alternate the order of local and tunneled runs when practical so that application warm-up or changing network conditions do not always favor one cohort.
Summarize each metric with the sample count and several percentiles. The median shows a typical observation in the collected sample. P75 provides a view farther into the slower part of the distribution, while P90 can expose a longer tail when the sample is large enough to support it. An average alone can hide both a majority of fast visits and a smaller set of severe delays.
| Measurement | Primary question | How to interpret a tunneled change |
|---|---|---|
| Request to first byte | How long until the document response begins? | A larger value points toward added path delay, application waiting, or both, but does not identify one network segment by itself. |
| Response download | How long does the document body take to arrive? | A change can reflect payload size, throughput, congestion, or pauses in application delivery. |
| LCP | When does the largest visible content render? | A later value may begin with document delay, late resource discovery, resource loading, or render-blocking work. |
| CLS | How much unexpected layout movement occurs? | A network change can alter when assets arrive, but layout instability is usually addressed in page structure, dimensions, fonts, and dynamic content behavior. |
| INP | How responsive is the page to user interaction? | If document timing is similar but INP worsens, investigate main-thread work, event handling, and presentation rather than blaming delivery latency. |
| DOM and load milestones | When do parsing and load events complete? | These milestones add context but are not substitutes for visual and interaction metrics. |
Compare deltas within matching segments
Calculate a local-versus-tunnel difference only inside comparable groups. For example, compare cold-cache desktop dashboard visits with other cold-cache desktop dashboard visits. Do not subtract a mobile landing-page P75 from a desktop dashboard median.
If document response timing increases through the tunnel while the interval from response start to LCP remains similar, delivery is likely contributing much of the observed difference. If document response timing changes only slightly but LCP grows substantially, inspect what happens after the HTML begins arriving. JavaScript-dependent resource discovery, stylesheet work, image decoding, font behavior, and rendering delays can all dominate the visual result.
A local-versus-tunneled delta is not automatically “tunnel latency.” Navigation Timing observes boundaries from the browser’s perspective. The public request crosses the visitor’s access network and internet route before reaching the relay path, then reaches the local service through the client’s outbound connection. Application processing and local-host resource contention remain part of the result. Browser timing does not cleanly assign milliseconds to each internal hop.
Add remote devices after the paired test
Once paired testing establishes a controlled comparison, invite a small group of authorized testers using representative devices. Keep their results segmented by device class, browser family, route, and coarse network scenario. This stage answers a different question: how the complete experience behaves for actual remote browsers.
Do not expect every external tester to produce the same result. Variation is the point of field measurement. Look for repeatable patterns, such as consistently late LCP on smaller devices or poor INP after opening a complex component. Investigate patterns that survive multiple visits rather than treating one isolated outlier as proof.
Distinguish frontend, application, tunnel-path, and network delays

Performance diagnosis is strongest when the timeline is divided into stages. Core Web Vitals describe the user-visible outcome. Navigation Timing describes document delivery boundaries. Application telemetry can describe server processing. Together, these layers narrow the search without pretending that one browser metric exposes every network hop.
Break down a slow LCP
A slow LCP can originate before or after the HTML document begins arriving. A useful conceptual breakdown includes document time to first byte, delay before the browser discovers the LCP resource, time spent loading that resource, and delay before it is rendered. This prevents a common mistake: compressing every visual delay into “the network.”
- Late document response: Check request-to-first-byte timing, application processing, dependency calls, and host resource contention.
- Late resource discovery: Inspect whether JavaScript must run before the browser learns about the primary image, font, or content request.
- Long resource load: Examine asset size, caching behavior, throughput, and whether the browser is competing for many resources.
- Long render delay: Investigate main-thread work, styles, layout, hydration, image decoding, and rendering dependencies.
Suppose the tunneled document starts 180 milliseconds later than the local document, but LCP is 900 milliseconds later. The path may explain part of the difference, but it cannot explain the full visual delay without further evidence. The slower arrival may also change resource scheduling or expose frontend work that was nearly invisible on localhost.
Break down a slow interaction
INP reflects the latency of user interactions. Its underlying experience can be considered in three broad phases: input delay while the browser waits to begin handling the event, processing time while event handlers and related JavaScript run, and presentation delay before the next visual update is painted.
- A high input delay often indicates that the main thread was already busy.
- A high processing duration points toward expensive event handlers or synchronous JavaScript work.
- A high presentation delay suggests expensive style calculation, layout, rendering, or other work before the updated frame appears.
A tunnel can affect interactions that require a network round trip, but not every interaction is network-bound. If opening a client-side menu is slow after all resources have loaded, inspect main-thread and rendering work first. If saving a form waits for an application response, correlate the browser interaction with application request timing while keeping the collected data minimal.
Watch the local application host
The development host itself can become the bottleneck. Debug middleware, live-reload tooling, just-in-time compilation, verbose logging, unoptimized asset generation, database containers, and unrelated workloads may delay requests. Record whether the application is running in a development or production-like build, and do not compare those modes as if only the network path changed.
If available in the application stack, record a server processing duration generated by the application. A random request correlation value can connect that duration to a browser observation without storing identity. Do not put access tokens, user IDs, email addresses, or request contents into the correlation field.
Use traces after RUM identifies the problem
RUM tells you where users experience pain and which segments are affected. A browser performance trace can then explain a small number of representative cases in detail. Record traces only after the RUM distribution points to a route or action. This avoids spending time analyzing one unusual profile that does not represent the broader test sample.
RUM is best for distributions and real browser outcomes. Controlled synthetic runs are best for repeatability. Browser traces are best for detailed main-thread diagnosis. Application telemetry is best for server-side processing. Combining them is more reliable than asking one measurement system to explain every layer.
Design the test for security and data minimization
A useful RUM record does not need to become a record of user behavior. Collect only fields required to answer the performance question, restrict the test to authorized participants, and define when the data will be deleted. Predeployment testing is an opportunity to establish these boundaries before telemetry reaches a larger audience.
Authenticate both the application and the collector
Use application-level authentication for nonpublic routes and test data. Create dedicated, least-privilege test accounts rather than exposing an administrator session. Because a same-origin /rum endpoint sits behind the same public address in the sample design, apply appropriate authorization, request validation, rate limiting, and abuse controls to it as well.
Do not send a Localtonet device token to the browser. The token identifies the client device that runs the tunnel and must remain private. Browser code needs only the application URL and its normal application authentication flow.
Minimize and normalize fields
- Use route groups instead of raw URLs.
- Exclude query strings and URL fragments.
- Do not collect form values or page text.
- Use coarse viewport or device categories instead of a fingerprint.
- Avoid persistent cross-session identifiers unless the experiment genuinely requires them and has been reviewed.
- Do not store full raw performance entries by default.
- Set a short retention period appropriate to the experiment.
- Restrict access to the resulting reports.
Keep test data separate from production data
Populate the local application with synthetic or sanitized records. A public tunnel should not become an accidental route to production customer information. Review background jobs, outbound email, payment integrations, webhooks, and third-party analytics before inviting testers. Disable or redirect side effects that should not run during a performance experiment.
End the exposure deliberately
Stop the Localtonet tunnel after the scheduled test window. A created tunnel is not necessarily running, and a stopped tunnel is no longer available through its active public route. Delete configurations that are no longer needed, revoke temporary application accounts, and remove or disable the RUM endpoint if it was created only for this experiment.
Authentication tokens, cookies, authorization headers, private endpoints, passwords, complete request bodies, and personal data do not belong in RUM payloads. If a telemetry field might contain user-controlled text, normalize or remove it before transmission.
Troubleshoot common RUM and tunnel test problems
The application works locally but not through the tunnel
Confirm that the local service is still running and listening on the IP address and port configured as the tunnel target. Verify that the Localtonet client is connected, the correct device is selected, and the tunnel has been started. Creating a tunnel does not automatically run it. If the service is reachable only from a different device, the client device must be able to reach that address over the local network.
Also inspect application assumptions about the public hostname and HTTPS origin. Development servers may enforce allowed-host checks, generate absolute URLs for a loopback origin, or redirect to a fixed local address. Resolve these behaviors in the application’s supported configuration rather than weakening host validation globally.
The page loads, but no RUM records arrive
Check the browser Network panel for the /rum request. Verify the endpoint path, accepted content type, authentication state, request-size limit, and server logs. Content blockers or privacy modes may suppress telemetry, and beacon delivery is not guaranteed. Treat telemetry as best effort and never make application functionality depend on successful collection.
If the application is a single-page application, ensure the module containing the instrumentation is loaded on the initial page and is not initialized repeatedly on every route transition. Duplicate initialization can produce duplicated observations. Measuring client-side soft navigations accurately may require framework-specific instrumentation beyond the initial document navigation shown in this guide.
LCP or CLS appears, but INP does not
INP requires user interaction. Perform the planned click, tap, or keyboard action and leave enough time for the metric implementation to observe and report it. A page that receives no qualifying interaction cannot provide an interaction responsiveness observation. Do not replace a missing INP value with zero.
Local records are labeled as tunneled
The example labels only localhost, 127.0.0.1, and ::1 as local. A LAN hostname, custom development domain, container gateway, or reverse proxy will fall into the other bucket. Replace hostname inference with an explicit environment label and validate it in the received payload.
Tunneled timing varies widely
Wide variation may be real. Check whether testers changed devices, networks, routes, cache states, or application accounts. Segment those factors before searching for one technical cause. On the development host, check compilation, CPU usage, memory pressure, database work, and background tasks. On remote devices, distinguish Wi-Fi from mobile data and avoid combining all observations into one average.
Transfer size is zero or missing
Browsers can expose different transfer-size behavior depending on cache use, protocol details, resource origin, and privacy restrictions. Keep missing values nullable and use them as supporting context rather than a required condition for a valid Core Web Vitals record.
The public result is slower than the local result
Some increase is unsurprising because the public request has a longer path than loopback. The useful question is where the additional time appears and whether the resulting experience meets the application’s objective. Compare request-to-first-byte timing, response download, LCP, and interaction behavior within matching cohorts. Do not assign the entire difference to the tunnel without application and network evidence.
Frequently asked questions
Can a localhost tunnel produce real Core Web Vitals?
Yes. Core Web Vitals are observed in the browser, so an instrumented page reached through a public tunnel can report LCP, CLS, and INP when the browser supports the required APIs and the relevant page activity occurs. The results describe that browser’s experience through the test path. They are not automatically representative of a future production deployment or all users.
Does the local-versus-tunnel difference equal Localtonet latency?
No. The difference can include the visitor’s access network, internet routing, the relay path, the client’s outbound connection, application processing, cache behavior, and browser variation. A paired same-device test reduces some variables, but browser timing still does not isolate every network segment.
Should I use RUM instead of a synthetic speed test?
Use both for different purposes. Synthetic tests provide controlled, repeatable conditions and are useful for regression testing. RUM shows the distribution of experiences across actual browsers, devices, networks, and interactions. Browser traces and application telemetry can then diagnose specific cases identified by either method.
How many visits are required before comparing percentiles?
There is no universal count for every experiment. Collect repeated observations for every matching scenario, publish the sample count beside each percentile, and avoid strong conclusions from a small sample. Higher percentiles require more observations to become stable. A small predeployment sample is useful for finding obvious regressions, but it should not be presented as population-wide field data.
Why can LCP be slow when the HTML response is fast?
The browser may receive the document promptly but discover the LCP resource late, spend time downloading another asset, or wait for JavaScript, CSS, layout, image decoding, fonts, or rendering work. Compare document timing with the interval after response start instead of treating LCP as a pure network metric.
Can I keep the Localtonet tunnel running permanently for RUM collection?
A tunnel remains available only while its selected client is connected and the tunnel is running. For a controlled predeployment test, define a test window and stop the tunnel afterward. Any longer-running exposure should receive the same security, authentication, maintenance, and data-governance review as another public application path.
What information should a privacy-conscious RUM payload contain?
Keep the payload focused on metric name, value, normalized route group, exposure type, broad device or viewport category, navigation type, and a timestamp when required. Exclude query strings, form values, cookies, authentication data, page content, and persistent user identifiers unless a separately reviewed requirement justifies them.
Test your local application with real browsers
Build the localhost baseline first, start a Localtonet HTTP tunnel, and compare matching browser journeys through the public HTTPS address. Keep the experiment authenticated, collect only the measurements you need, and stop the tunnel when testing is complete.
Get Started Free →