A page speed watcher on AWS for a few dollars a month
Almost every page speed setup fails the same way. Somebody runs a tool, gets a score, shares it, and three weeks later runs it again and gets a different score. Nobody knows whether the site got slower or the measurement did, so nothing happens, and eventually the checking stops. This post walks through a small system built around the one property that fixes it: measuring the same thing, the same way, enough times to know what noise looks like.

Key takeaways
- A short list of pages, chosen deliberately. Not every page, and not the home page only.
- One device and network profile, fixed forever. Changing it invalidates the whole history.
- Several samples per run, because a single page load is not a measurement.
- A regression is reported only when it exceeds the noise the site’s own history shows.
- Designed on AWS for about $4 a month.
The whole system on one page
Before any code, here is the shape of what we are designing.
- Management
- Analytics
- Front-end & mobile
- People
A single page load is not a measurement
Load the same page ten times on the same connection and the numbers will differ by twenty per cent or more. Server warm-up, network variance, CDN cache state, a third-party script that is slow this minute. None of that is your site changing, and all of it looks exactly like your site changing if you measure once.
So every run takes several samples of every page and keeps the median. That single decision is what makes everything downstream possible: with a median of nine samples you can say what normal variation looks like, and once you know that, you can say when something is outside it.
What runs daily (the inside)
- The measurer. Loads each page on the list several times in a headless browser on a fixed CPU and network profile, and records the metrics plus the full resource list. Part 2 covers the profile and why it must never change.
- The comparer. Takes the median for each page and compares it against a rolling baseline of the last few weeks, using the spread of that baseline to decide what counts as a change. Part 3 is entirely about this.
- The reporter. When something regresses, works out what got heavier by diffing the resource lists, and correlates the timing against the deploy feed. The output is “the hero image is now 1.4MB rather than 180KB”, not “LCP increased”.
One regression, end to end
In plain words
The pricing page has had a largest-contentful-paint median between 1.8 and 2.2 seconds for three weeks, measured nine times a day on a throttled mid-range mobile profile. On Wednesday the median is 3.9 seconds. That is well outside the range the page has shown across sixty-three previous runs, so it is a regression rather than a bad day.
The reporter diffs Wednesday’s resource list against Tuesday’s. One image on the page is now 1.4 megabytes where it was 180 kilobytes. The deploy feed shows a release at 09:12 on Wednesday, and the first slow run was 09:40. The message says all of that in three lines: the page, the number, the resource, and the release.
Somebody looks and finds that a new hero image was uploaded through the CMS without being resized. It is a five-minute fix, and the value of the system is entirely in somebody finding out on Wednesday rather than in three months when a customer mentions the site feels slow on their phone.
Design rules that shaped every decision
- One profile, forever. The absolute number is far less important than comparability.
- Several samples, always. A single load is not a measurement and treating it as one produces a tool nobody trusts.
- Compare against the site’s own spread, not a fixed threshold. Every page has a different amount of natural variation.
- Name the resource, not the metric. “LCP up 1.7s” is a fact; “the hero image is now 1.4MB” is a fix.
- Never block a deploy. A noisy gate is a gate people learn to bypass.
- A short page list. Eight pages measured properly beats four hundred measured once.
Why this shape
Web performance monitoring has a credibility problem, and it is self-inflicted. Tools report a score, the score moves for reasons unrelated to the site, and everybody learns to discount it. By the time something genuinely regresses, the signal has no audience.
So this design spends nearly all of its effort on making the number trustworthy: a fixed profile, many samples, and a comparison that understands its own noise. The measuring is a headless browser and a library, which is the least interesting part, and the reporting is short because a trustworthy number does not need much explanation.
The next four posts walk through each piece: how a page gets measured, how a regression is distinguished from noise, how a budget is set, and what the report says. One diagram per post, a cost breakdown, and an engineering reference at the end.
All posts