skip to content

A front-end team wants to know what real browsers experience on your site, not just what the servers logged. What does Amazon CloudWatch RUM collect, how does a browser get permission to send that data, and which levers control its volume?

level: middleimportance: should knowfreq 32%

answer

  1. real browsers, not a scripted probe
  2. app monitor per application
  3. browser credentials from a Cognito guest role
  4. sampling happens per session
  5. URLs leak more than you think

basics

~20 s

CloudWatch RUM embeds a JavaScript client in your pages that reports page-load performance, Core Web Vitals, JavaScript errors, failed HTTP calls and session/browser context to an app monitor. The browser authorizes with temporary guest credentials from an Amazon Cognito identity pool, and a session sample rate controls volume.

solid answer

~50 s

CloudWatch RUM is passive, client-side telemetry: you create an **app monitor** for a domain and add the `aws-rum-web` client to your pages. It collects page views and load timings including Core Web Vitals such as largest contentful paint and cumulative layout shift, uncaught JavaScript errors with stack traces, failed or slow HTTP requests made by the page, and session context — browser, device, country. That answers questions synthetic probing cannot: which browsers are slow, which country regressed, which error only your users hit. Authorization is the interesting part: the code runs in an untrusted browser, so RUM does not use long-lived keys. The client fetches temporary credentials from an **Amazon Cognito identity pool** configured for unauthenticated (guest) identities, whose role is scoped to `rum:PutRumEvents` on that app monitor's ARN — the narrowest permission that still lets anonymous visitors report. The volume levers are `sessionSampleRate`, which decides what fraction of sessions is recorded at all, and the `telemetries` list, which decides what each recorded session sends.

code

javascript · 17 lines
javascript
import { AwsRum } from 'aws-rum-web';

try {
  new AwsRum(
    'APPLICATION_ID',
    '1.0.0',
    'eu-west-1',
    {
      identityPoolId: 'eu-west-1:1111aaaa-2222-3333-4444-5555bbbbcccc',
      sessionSampleRate: 0.1,
      telemetries: ['errors', 'performance', 'http'],
      allowCookies: true
    }
  );
} catch (e) {
  // never let telemetry break the page
}

go deeper

for a junior

Know that RUM collects telemetry from real visitors' browsers — load performance, JavaScript errors, failed requests — by including an AWS-provided script in your pages.

for a middle

Explain the app monitor, the telemetry categories, and that the browser authorizes via a Cognito identity pool's guest role scoped to rum:PutRumEvents on that app monitor.

for a senior

Show the operating judgment: sample per session for cost, scope the guest role tightly, treat the data as attacker-influenceable and never expect it to reconcile with server counts.

for a principal

Own the tradeoff between insight, ingestion spend and privacy exposure — what the URLs may carry, how consent interacts with session cookies, and where real-user data justifies its cost against synthetic coverage.

## Passive versus active A Synthetics canary tells you whether a scripted journey works from an AWS region. It cannot tell you that your site is slow on mid-range Android phones in Brazil, or that a third-party tag throws only in Safari. That requires observing **real sessions**, which is what CloudWatch RUM does. The two are complements, not alternatives: a canary gives you a signal when nobody is using the site; RUM gives you the truth when they are. ## The app monitor The RUM resource is an **app monitor**, created per application/domain. It holds the domain the client is allowed to report from, the telemetry configuration, the identity configuration, and optionally a destination for a copy of the raw events. Creating it yields an application id that the client is initialised with. ## What it collects - **Page views and navigation timing**, including Core Web Vitals such as largest contentful paint and cumulative layout shift — the metrics that describe perceived load, not server time. - **JavaScript errors**, with message and stack, which is often the only place a client-side failure is visible at all. - **HTTP requests** issued by the page (`fetch`/`XMLHttpRequest`), with status and timing, so you see what the browser experienced rather than what the server logged. - **Session context** — browser, OS, device type, country — which is what makes the data actionable, because "slow" is almost always slow *for a segment*. ## The authorization model This is the part worth understanding properly, because it is a real security design and interviewers like it. The code that sends RUM data runs in the browser of an anonymous visitor. You cannot ship an access key. So the client obtains **temporary credentials from an Amazon Cognito identity pool** with unauthenticated identities enabled. The pool's guest role grants exactly one thing: ```json { "Effect": "Allow", "Action": "rum:PutRumEvents", "Resource": "arn:aws:rum:eu-west-1:111122223333:appmonitor/storefront" } ``` The blast radius of someone lifting those credentials is therefore "can post events to this one app monitor" — annoying (junk data, some cost) but not a breach. Two consequences follow: **scope the role to the specific app monitor ARN**, never to `*`; and treat RUM data as **attacker-influenceable**, because anyone can post to that endpoint. It is telemetry, not an audit trail. When the page already has authenticated AWS credentials of its own, the client can be handed those instead of using the guest pool. ## Configuring the client ```javascript import { AwsRum } from 'aws-rum-web'; new AwsRum('APPLICATION_ID', '1.0.0', 'eu-west-1', { identityPoolId: 'eu-west-1:1111aaaa-2222-3333-4444-5555bbbbcccc', sessionSampleRate: 0.1, telemetries: ['errors', 'performance', 'http'], allowCookies: true }); ``` The levers: - **`sessionSampleRate`** — the fraction of sessions recorded. Sampling in RUM is *per session*, not per event, which matters: a sampled session is complete and reconstructable, rather than a scatter of unrelated fragments. Turning this down is the primary cost control. - **`telemetries`** — which collectors run. Dropping `http` or `performance` cuts volume for sites that only care about errors. - **`allowCookies`** — whether the client stores a cookie to stitch page views into a session. With it off you still get events but lose session continuity, which is the usual privacy-driven trade. ## Privacy, and what not to collect RUM observes real people, so it lands squarely in privacy review. The default data is technical, but a URL is not: query strings and path segments routinely carry email addresses, tokens and order identifiers, and those get recorded as page identifiers. Scrub or normalise URLs before they are reported, keep the cookie decision aligned with your consent banner, and set expectations that RUM is aggregated diagnostics rather than per-user tracking. ## Costs and gotchas - RUM bills by **events ingested**, so a busy site at 100% sampling is expensive for no extra insight; most estates run a low single-digit or ten-percent sample and raise it temporarily during an investigation. - A **single-page application** does not issue real navigations, so route changes need the client's own page-view recording to appear as distinct pages. - Ad blockers and privacy browsers will drop some of the beacons. RUM is representative, never a complete census — do not reconcile it against server counts and expect them to match. - The app monitor is tied to the domains you configure; reporting from an unlisted origin does not appear.

  • Why does CloudWatch RUM sample per session rather than per event?
    Because a partial session is close to useless. If individual events were dropped independently you would get a page load with no errors attached and errors with no navigation context. Sampling whole sessions means every recorded session is internally complete and reconstructable, at the cost of a coarser sample.
  • What is the worst outcome if someone extracts the Cognito guest credentials from your page?
    They can call rum:PutRumEvents against that one app monitor — meaning junk telemetry and some ingestion cost, provided the guest role is scoped to that app monitor's ARN and nothing else. That is why the role must never be broadened; a permissive guest role hands anonymous visitors real API access.
  • How would you use RUM and Synthetics together during an incident?
    The canary tells you whether the critical path is reachable at all and gives you a screenshot and HAR from the failing run. RUM tells you who is actually affected — which browsers, regions and pages — and whether the error is client-side. Canaries detect, RUM scopes the blast radius.
  • What privacy work does adding RUM to a production site imply?
    Reviewing what the URLs and page identifiers carry, since query strings and paths often contain emails, tokens or order ids that would be recorded verbatim; deciding the cookie behaviour against your consent banner; and being clear internally that it is aggregate diagnostics rather than per-user tracking.

saying these in an interview costs you the question

  • Assuming RUM replaces synthetic canaries
  • Granting the Cognito guest role broad permissions instead of one app monitor
  • Running 100% session sampling on a high-traffic site
  • Treating RUM data as trustworthy, non-forgeable input
  • Expecting RUM counts to reconcile exactly with server-side request counts
  • Reporting raw URLs that carry tokens or email addresses

context