Back to category
Frontend

RUM vs Synthetic Monitoring: What's the Difference?

RUM measures real user experience; synthetic monitoring runs scripted tests on a schedule. Compare coverage, Core Web Vitals, alerting, and cost.

Real user monitoring (RUM) collects performance and error data from the browsers and devices of people actually using your site, while synthetic monitoring runs scripted tests from controlled locations on a fixed schedule. RUM tells you how your application performs for real users across every device and network. Synthetic monitoring tells you whether a page or user flow works right now, even when nobody is using it.

TL;DR

  • RUM is passive field data from real sessions. Synthetic monitoring is active lab data from scripted runs.
  • Synthetic tests catch outages at 3 a.m. with zero traffic and gate releases in CI. RUM shows the long tail of slow devices, networks, and regions you never scripted.
  • Interaction to Next Paint (INP) is a field metric. Synthetic tests can approximate it, but only RUM reports the INP value real users experience.
  • Use synthetic monitoring for availability alerts and regression checks. Use RUM for Core Web Vitals, user impact, and prioritization.
  • Most teams need both, connected to backend traces so a slow page leads straight to the slow service.

What Is Real User Monitoring (RUM)?

RUM uses a small JavaScript snippet (or a mobile SDK) that records timing, errors, and interactions from every real page view and sends them to a collector. Because it measures real sessions, the data reflects actual devices, browsers, network conditions, and geographies, including the slow Android phone on a congested network that no test lab reproduces. RUM data is analyzed as distributions and percentiles rather than single results. See What Is Real User Monitoring? for the full definition.

What Is Synthetic Monitoring?

Synthetic monitoring runs automated checks against your application at regular intervals from chosen locations. Checks range from a simple HTTP request that verifies a 200 response, to an API sequence, to a full browser script that logs in, adds an item to a cart, and checks out. Because the device, network, and location are fixed, results are repeatable and comparable run to run. See What Is Synthetic Monitoring? for the full definition.

RUM vs Synthetic Monitoring at a Glance

DimensionReal user monitoring (RUM)Synthetic monitoring
Data sourceReal sessions (field data)Scripted runs (lab data)
Monitoring stylePassive: waits for trafficActive: generates its own traffic
Works with zero trafficNoYes
EnvironmentEvery real device, browser, network, regionFixed device profile, network, and locations you choose
Best signalPercentile distributions (p75, p95)Pass or fail, and trends of consistent runs
Core Web VitalsLCP, INP, and CLS as users experience themLCP and CLS in lab conditions; INP only approximated
Preproduction useNo real users yetYes, including CI gates
Finds unknown problemsYes, any page or flow users hitOnly in flows you scripted
Cost driverSessions or events collectedChecks multiplied by locations and frequency
Privacy considerationsCollects data from real users; needs masking and consentUses test accounts; minimal user data

Key Differences Explained

Field Data vs Lab Data

RUM produces field data and synthetic monitoring produces lab data. MDN's performance guide describes RUM as better suited to long term trends and synthetic monitoring as better suited to regression testing and short term issues. The two will disagree, and that is expected: a lab run on a fast desktop profile says nothing about the p75 user on a midrange phone.

This gap explains a common frustration. A page can score well in a Lighthouse lab run and still fail Core Web Vitals, because Google assesses real user data from the Chrome UX Report, not lab results.

Which Failures Each One Catches

This is the most practical way to decide what you need:

FailureRUMSynthetic
Site fully down overnight with no trafficMisses it (no sessions)Catches it within one check interval
Checkout broken for all usersCatches it once users hit itCatches it if checkout is scripted
Slow pages on low end Android devices in one countryCatches itMisses it unless that exact profile and location is tested
A third party script slowing interactions for some usersCatches itOften misses it (script may behave differently for bots)
Regression introduced in a pull request before deployMisses it (not in production)Catches it in CI
SSL certificate expired or DNS misconfiguredCatches it after users failCatches it immediately
JavaScript error on a rarely visited pageCatches itMisses it unless scripted
Gradual p75 LCP drift over three weeksCatches itMay miss it (lab conditions stay constant)

The pattern: synthetic monitoring answers "is it working?" for known paths, and RUM answers "how is it working for everyone?" across paths you never thought to test.

Core Web Vitals: Why INP Needs RUM

Google's Core Web Vitals are assessed at the 75th percentile of page loads, segmented by mobile and desktop. The "good" thresholds are:

MetricMeasuresGoodPoorMeasurable in synthetic tests?
Largest Contentful Paint (LCP)Loading2.5 s or lessOver 4 sYes, under lab conditions
Interaction to Next Paint (INP)Responsiveness200 ms or lessOver 500 msOnly approximated
Cumulative Layout Shift (CLS)Visual stability0.1 or lessOver 0.25Partly (load time shifts only)

INP measures the latency of real interactions across the whole page visit, so a scripted run has only the interactions you chose to simulate. web.dev's INP documentation notes that Total Blocking Time (TBT) can be a reasonable lab proxy for INP but is not a substitute. If INP is the metric holding your pages back, you need RUM to see it.

Alerting Behavior

Synthetic alerts are deterministic: two consecutive failures from two locations is a clear, low noise paging condition. RUM alerts are statistical: they need enough sessions to compute a stable percentile, so they work well for "p75 LCP on /checkout above 3 s for 30 minutes" but poorly for low traffic pages or overnight windows.

A practical split is to page on synthetic availability failures and on RUM error rate spikes for high traffic flows, and to open tickets for RUM Core Web Vitals regressions.

Cost and Data Volume

Synthetic cost scales with checks, locations, and frequency. For example, 5 browser checks run from 3 locations every 5 minutes is 5 × 3 × 12 runs per hour, or 129,600 runs in a 30 day month. Halving frequency to every 10 minutes halves that cost but doubles worst case detection time.

RUM cost scales with traffic. High traffic sites usually sample sessions (for example 10% to 20%) and keep 100% of error sessions, so rare failures are not sampled away.

When to Use RUM

  • You need Core Web Vitals, especially INP, as users actually experience them.
  • You want to know which pages, browsers, devices, or regions have the worst experience, and how many users are affected.
  • You need to prioritize frontend work by user impact rather than by lab scores.
  • You want to connect frontend slowness to specific backend services.

When to Use Synthetic Monitoring

  • You need to know about outages when traffic is low or zero.
  • You have critical flows (login, checkout, signup) that must be verified continuously.
  • You want to catch regressions before release by running checks in CI or staging.
  • You need to monitor third party APIs, SSL certificates, or DNS from multiple regions.
  • You need a stable baseline to compare releases without real world noise.

Using RUM and Synthetic Monitoring Together

The strongest setups connect both approaches in one workflow:

  1. Synthetic checks guard critical flows. Browser checks for login and checkout run every 5 minutes from 3 or more regions and page on repeated failures.
  2. RUM confirms blast radius. When a synthetic check fails, RUM shows whether real users in that region are affected and how many.
  3. RUM finds what to script next. When RUM shows a slow or error prone flow you are not testing, add a synthetic check for it.
  4. Traces connect frontend to backend. Propagating W3C Trace Context headers from the browser lets you jump from a slow RUM page load or failed synthetic step to the backend trace that caused it.

Collecting Core Web Vitals for RUM takes a few lines with Google's web-vitals library:

import { onLCP, onINP, onCLS } from 'web-vitals';

function sendToCollector(metric) {
  const body = JSON.stringify({
    name: metric.name,     // "LCP", "INP", or "CLS"
    value: metric.value,
    rating: metric.rating, // "good", "needs-improvement", or "poor"
    page: location.pathname,
  });
  // sendBeacon survives page unload, which is when INP and CLS finalize
  navigator.sendBeacon('/rum', body);
}

onLCP(sendToCollector);
onINP(sendToCollector);
onCLS(sendToCollector);

A synthetic browser check for the same site, written with Playwright:

import { test, expect } from '@playwright/test';

test('checkout flow is available', async ({ page }) => {
  await page.goto('https://shop.example.com/');
  await page.getByRole('button', { name: 'Add to cart' }).first().click();
  await page.getByRole('link', { name: 'Cart' }).click();
  // Fail fast: a checkout button that takes over 5s to render is an incident
  await expect(page.getByRole('button', { name: 'Checkout' })).toBeVisible({ timeout: 5000 });
});

RUM and Synthetic Monitoring with Middleware

Most teams struggle less with collecting RUM and synthetic data than with connecting it to the backend when something breaks. Middleware runs RUM, synthetic monitoring, and browser testing on the same platform as APM, logs, and infrastructure monitoring, so a failed checkout check or a slow real user session sits on one timeline with the backend traces and logs behind it. Because the platform is OpenTelemetry native, backend services instrumented with standard SDKs appear without proprietary agents. Set up real user monitoring in Middleware.

Frequently Asked Questions

Is synthetic monitoring the same as synthetic testing?

Mostly, yes. The terms are often used interchangeably. Synthetic testing usually refers to running scripted checks before release, for example in CI or staging, while synthetic monitoring refers to running the same kind of checks continuously against production on a schedule. Many teams reuse the same scripts for both, which keeps preproduction and production checks consistent.

Can synthetic monitoring measure Core Web Vitals?

Partly. Synthetic tests can measure LCP and load time CLS under the lab conditions you configure, which is useful for catching regressions. They cannot report real INP because INP depends on real user interactions across a whole visit, so lab tools use Total Blocking Time as a proxy. Google evaluates Core Web Vitals using real user data, so you need RUM for the numbers that count.

Does RUM slow down my website?

A well built RUM script adds very little overhead. Modern RUM libraries load asynchronously, batch data, and send it with navigator.sendBeacon when the page is hidden or unloads, so they do not block rendering or interactions. Check the script's compressed size, load it after critical resources, and sample sessions on very high traffic sites to control data volume.

How often should synthetic checks run?

Match frequency to how quickly you need to know. Critical flows like login and checkout commonly run every 1 to 5 minutes from at least 3 locations, with alerts after 2 consecutive failures to avoid noise. Less critical pages can run every 15 to 30 minutes. Remember that cost scales with checks, locations, and frequency.

Do I need both RUM and synthetic monitoring?

Most production web applications benefit from both. Synthetic monitoring gives you availability alerts when traffic is low and a way to test releases before users see them. RUM shows what real users experience across devices and regions, including problems in flows you never scripted. Small sites with low traffic can start with synthetic checks and add RUM as traffic grows.