Performance budgets that actually hold
A performance budget isn’t a document you write and forget. It’s a simple rule that stops the build when you cross the line and shows up in every PR.
Most teams deal with performance in an “optimisation week”. The product slows down, a few weeks go into fixes, then everything drifts back. A performance budget is the simplest way we know to break that cycle.
Measure a few things, but the right ones
When you try to measure everything, nobody looks at anything. We usually start with three numbers:
- LCP: how quickly does the main content appear?
- INP: how fast does the interface react when you press something?
- CLS: how much does the content jump around while the page loads?
On top of those, we cap the size of the JavaScript we ship. User-side numbers tell you about a problem late. Bundle size catches it before the code is even merged.
Make the budget visible
A budget that only lives in someone’s head doesn’t work. Put it in your test pipeline and stop the build when it’s exceeded:
{ "budgets": { "lcp_ms": 2500, "inp_ms": 200, "cls": 0.1, "js_kb_gzip": 170 }}A short note on every pull request showing how these numbers moved turns “it feels slower” into “LCP went up 300 ms”.
Write down the exceptions
Sometimes going over the limit is the right call, when a new feature genuinely adds value. What matters is doing it on purpose. Note every change that raises the budget, along with the reason.
Speed is a feature too, and every feature needs an owner.
We built this site by the same rules. Pages are prepared in advance, fonts come from our own server, and instead of heavy animation libraries we only ship the code that’s needed.