advanced 3 min answer

A booking site enforces a performance budget in CI: the main bundle must stay under 300 KB compressed. The budget has passed on every build for a year. Field data shows the median page is 2.8 MB of JavaScript and interaction latency has doubled. Review the budget. What is wrong with it, and what would you replace it with?

performance-budgetthird-partyrumgovernancejavascript
Show the full answer Hide the answer

What is actually being measured

The budget measures the artefact the build produces, and the page loads code the build never sees. Everything in the gap is unbudgeted by construction:

  • Tag managers, which are a loader for scripts chosen later by someone outside engineering.
  • Analytics, session replay, consent management, A/B testing, chat widgets, fraud and ad scripts, each injecting more at runtime.
  • Lazily-loaded application chunks, which a bundle-size check on the entry point does not count.
  • Third-party code that loads its own third parties, so one tag becomes a tree whose depth nobody has measured.

The budget is not lying. It is answering a question about the build in a review about the user, and it has been passing while the thing it was bought to prevent happened.

What I would remove

  • The single compressed-bundle threshold as the primary gate. Keep it as a regression detector for the build, and stop presenting it as the performance budget. It has one virtue — it is fast and deterministic — and one fatal flaw for this purpose.
  • Any budget expressed only in bytes. Bytes are a proxy for the thing that hurts, which is main-thread time: 300 KB of JavaScript must be parsed, compiled and executed, and on a mid-range Android phone that work is several times slower than on the developer's laptop. Two payloads of equal size can differ by a factor of three in how long the page is unresponsive.

What I would replace it with

Three budgets at three levels, because one number cannot cover them:

  1. A field budget, which is the one that decides whether you are winning. Real-user metrics at p75, per route, on the devices your users actually have: the loading metric, the interaction-responsiveness metric and layout stability. Interaction to Next Paint has been a Core Web Vital since 12 March 2024 and is the one to watch here, because it measures the full interaction including processing and the next paint, which is exactly the "site feels slow" complaint.
  2. A lab budget on the assembled page, not the bundle. A synthetic run of the real page with the real tags, throttled to a named device and network profile, asserting total transferred bytes, script execution time and the metrics above. This is the check that would have failed a year ago.
  3. A third-party budget with a named owner. A count and a byte and main-thread allowance for non-application scripts, enforced by a content security policy that refuses unlisted origins, so adding a tag is a change with a review rather than a configuration edit. The mechanism matters more than the number: a budget with no enforcement point is a wish.

What I would leave alone

The CI check itself, running fast on every pull request. It is cheap, it catches a dependency that doubles in size, and it fails in seconds. The mistake was its scope, not its existence.

How I would argue this in the review

Not as "the budget is wrong", which invites a defence of the number. Put the field data next to the passing build: a year of green checks alongside a doubling of interaction latency is an argument that makes itself. Then name the owner problem out loud, because the real finding is organisational — the scripts that broke the budget were added by people the budget did not apply to, and no threshold fixes that. The deliverable from the review is a named owner for third-party weight and a pipeline gate on the assembled page.

When this is over-engineering

A content site with no third-party scripts and one bundle does not need three budgets. The lab check on the real page is enough, and adding field monitoring to a site with 2,000 visits a month produces data too sparse to act on. The three-level structure earns its cost when marketing can add scripts to production, which is the condition that created this question.