Issue 14PlaybookNo. 010
The 1 MB page budget: how we keep client sites fast long after launch.
Performance decays one plugin and one hero video at a time. The budget, CI checks and review rituals that stop the slide.
Rafael Santos
Partner · Engineering
- Published
- Updated
- Read time
- 8 minutes

In this article
Most sites are at their fastest on launch day. Then a chat widget arrives, a marketing tag, a hero video, a second analytics tool — and eighteen months later nobody can say when the site got slow, only that it did.
We stopped treating speed as a launch checklist item years ago. Every site we build now ships with a performance budget: a hard ceiling on what a page is allowed to weigh, enforced by the build and reviewed by people. The headline number is 1 MB. This is how it works, and why it holds.
Why a budget beats a score
Lighthouse scores are useful, but they make a poor contract. They move between runs, they depend on the machine running the test, and a score of 92 doesn't tell a marketer whether they can add one more script. A budget does. “This page may transfer 1 MB on first load” is a sentence anyone on the team can understand, check and argue with.
It also tracks what visitors actually feel. Page weight isn't a Core Web Vital, but it drives two of them. Heavy images and render-blocking files push out Largest Contentful Paint; heavy JavaScript ties up the main thread and hurts Interaction to Next Paint. Google's thresholds for a good experience are an LCP of 2.5 seconds or less, an INP of 200 milliseconds or less and a Cumulative Layout Shift of 0.1 or less, measured at the 75th percentile of real visits. Keeping pages light is the cheapest way we know to stay inside them on mid-range phones and patchy connections.
How we split the megabyte
The 1 MB is the total compressed transfer for a typical page on a first visit, before anyone interacts with it. We split it into line items, so that a breach points at a culprit rather than a mystery.
| Resource | Budget (compressed) | What usually breaks it |
|---|---|---|
| HTML | 50 KB | Inlined data blobs, page-builder markup |
| CSS | 60 KB | Unused framework and theme styles |
| JavaScript | 300 KB | Tag managers, chat widgets, sliders |
| Fonts | 100 KB | Too many weights, no subsetting |
| Images and media | 490 KB | Uncompressed heroes, autoplay video |
Templates differ — a product listing carries more images than a contact page — so we set the budget per template, not per site. Articles and landing pages usually come in well under. The home page is where the fight happens.
Field note · Hero video
A hero video is the fastest way to blow a budget. If the brief needs one, we ship a compressed poster image as the LCP element, load the video after the page is interactive, and skip it entirely when the visitor has Save-Data or reduced motion turned on.
Checks that fail the build
A budget nobody enforces is a wish. We wire ours into continuous integration, so every pull request is measured before it can merge.
Lighthouse CI on key templates.
Each pull request runs Lighthouse against the home page, a listing page and an article, with assertions on total byte weight, script size, LCP and layout shift. A breach fails the check.
Bundle size limits.
JavaScript bundles are measured at build time. Any route that grows past its limit needs a reviewer to approve the increase, with the reason written in the pull request.
Image rules in the pipeline.
Images are resized and converted to modern formats such as AVIF or WebP automatically, with explicit dimensions so nothing shifts while loading. Oversized uploads are rejected, not quietly served.
Third-party scripts behind one door.
Every external script loads through a single, documented place — usually the tag manager or one component — so the full list is visible at a glance and each one's cost can be measured.
Lab checks catch regressions before they ship. They don't tell you what real visitors experience, so we also collect field data: the web-vitals library reporting into analytics, plus the Chrome UX Report for sites with enough traffic to appear in it. When the two disagree, field data wins.

The rituals that stop the slide
Most performance regressions on client sites don't come from developers. They come from reasonable requests: a new pixel for a campaign, a review widget, a pop-up for the sale. So the last layer is process, not tooling.
- One in, one out. A new third-party script needs a named owner, a reason and an end date. If the page is already at budget, something else has to go.
- A monthly performance review. Fifteen minutes with the client's marketing lead: field Core Web Vitals, the budget report and every script added since last month.
- Campaign tags expire. Pixels added for a promotion are removed when the promotion ends, not when someone eventually notices.
- Guidance for editors. A one-page guide to image sizes, embeds and video, written for the people who publish rather than the people who build.
None of this is clever. It works because it turns performance from a one-off project into a habit with a number attached.
“Sites don't get slow in one release. They get slow one reasonable request at a time — so the budget has to be just as persistent.”
When the budget is the wrong number
1 MB isn't sacred. A photography portfolio or a product configurator may need more, and that's fine as long as the trade is explicit: where the extra weight goes, what it buys and how it loads. Interactive tools can load their heavy code only when someone opens them. Galleries can lazy-load everything below the first screen. What we won't accept is weight that arrives by accident.
The opposite happens too. For a landing page that lives on paid traffic, we often set the budget lower: every extra second between the ad click and a usable page is spend you've already paid for. If you'd like a second opinion on where your own pages stand, our web development team runs this audit as a fixed-scope project.
Key takeaways
If you only remember three things
Set a byte budget per template. It's a clearer contract than a Lighthouse score.
Enforce it in CI, and back the lab checks with field data from real visitors.
Most regressions arrive as reasonable requests — give every script an owner and an end date.

Written by
Rafael Santos
Partner · Engineering · 15 years shipping software
Rafael leads engineering across our web, app and CRM projects. He has shipped products on most of the stacks clients ask us about, and writes here about the technical decisions that age well — and the ones that don't.


