An Introduction to Web Performance Budgets
Every slow website got slow the same way: one reasonable decision at a time. A tracking pixel here, a chat widget there, a slider plugin because the client asked, a second font family because the first one lacked a good bold. No single addition felt expensive. Nobody approved a four-second load time. It just accumulated, the way clutter accumulates in a garage — because nothing ever had to justify its place.
A performance budget is the mechanism that forces the justification. It's a number — or a small set of numbers — that your site is not allowed to exceed. Total page weight under 1.5 MB. JavaScript under 300 KB. Largest Contentful Paint under 2.5 seconds on a mid-range phone. The specific figures matter less than the existence of a line, because the line changes the conversation. "Should we add this widget?" becomes "this widget costs 180 KB — what are we removing to pay for it?" That's the entire trick, and it's remarkably effective.
Why budgets work when good intentions don't
Performance regressions are invisible at the moment they happen. The person installing a plugin sees a feature appear; they don't see the 90 KB of JavaScript it enqueued on every page, because their own connection is fast and their cache is warm. The cost lands on a first-time visitor on hotel Wi-Fi three weeks later, and nobody connects the two events.
A budget makes the invisible visible at decision time. It also does something subtler: it removes performance from the realm of taste. Without a budget, "this is getting heavy" is one person's opinion against another's "it looks fine to me." With a budget, the site either fits or it doesn't. Arguments about numbers are shorter than arguments about feelings.
There's an analogy to financial budgets that's worth taking seriously: the point is not that you never spend, it's that spending is allocated. A performance budget doesn't forbid a big beautiful hero image — it makes you fund it by economizing elsewhere.
The three kinds of budget metrics
Budgets come in three flavors, and a decent setup uses at least two of them.
1. Quantity budgets (easiest to enforce)
Raw counts and byte sizes: total transferred bytes, bytes of JavaScript, bytes of CSS, number of requests, number of web fonts, number of third-party origins. These are blunt instruments — 300 KB of well-deferred JavaScript hurts less than 150 KB of render-blocking JavaScript — but they're trivially measurable, perfectly stable, and impossible to argue with. They're the checkbook register of performance.
2. Timing budgets (closest to user experience)
The Core Web Vitals and their cousins: Largest Contentful Paint (LCP), Interaction to Next Paint (INP), Cumulative Layout Shift (CLS), Time to First Byte (TTFB). These measure what users feel, which makes them the metrics that matter most — and the noisiest, since they vary with device, network, and server load. Timing budgets should be checked against consistent lab conditions (same throttling, same simulated device every time) and, ideally, validated against field data.
3. Score budgets (fine as a summary, weak as a target)
"Lighthouse performance score above 85." Composite scores are convenient for dashboards but make poor primary budgets, because they hide what regressed and their weighting changes between tool versions. Use a score as a smoke alarm, not as the budget itself.
Sensible starting numbers for a WordPress site
These are rules of thumb, not laws — calibrated for a content or small-business site that wants to feel fast on an ordinary phone over an ordinary mobile connection. Adjust deliberately, not accidentally.
| Metric | Budget | Notes |
|---|---|---|
| Total page weight | ≤ 1.5 MB | Under 1 MB is excellent; over 3 MB needs a reason |
| JavaScript (compressed) | ≤ 300 KB | The scarcest resource — phones must parse and execute it, not just download it |
| CSS (compressed) | ≤ 100 KB | Page builders routinely triple this; that's a finding, not a fact of life |
| Web font files | ≤ 3 files / 150 KB | Or one variable font |
| Third-party origins | ≤ 5 | Each origin is a connection cost and a reliability dependency |
| LCP (lab, throttled mobile) | ≤ 2.5 s | Google's "good" threshold |
| CLS | ≤ 0.1 | Mostly a discipline metric: dimensions on images, no injected banners |
| TTFB | ≤ 600 ms | Largely a hosting and caching question — the budget your host must meet |
Two observations about this table. First, JavaScript gets the strictest scrutiny relative to its size because its cost is nonlinear: a phone that downloads 300 KB of images just displays them, but 300 KB of JavaScript must be parsed, compiled, and executed on the main thread, blocking interaction. Second, TTFB is the one line item you mostly buy rather than build — server-level page caching and decent hosting solve it; no amount of front-end tuning can rescue a 1.8-second server response.
How to set your budget (two honest methods)
Method 1: budget from where you are
Measure your current site, then set the budget at current numbers minus a little. If your pages weigh 2.4 MB today, a 1.5 MB budget is a project; a 2.2 MB budget is a starting fence that at least stops things getting worse. Ratchet it down each quarter. This is the pragmatic path for existing sites — the budget's first job is to halt regression, and improvement comes second.
Method 2: budget from the competition
Pick the two or three competitors you most want to beat, run their sites through PageSpeed Insights or WebPageTest, and set your budget meaningfully below their numbers. Rationale: performance is partly a comparative advantage. A visitor bouncing between three local plumbers' sites doesn't know what LCP is, but they know which site answered first. Being noticeably faster than the field is a budget with a business case attached.
Either way, write the budget down somewhere visible — a pinned doc, the project README, the top of your maintenance checklist. An unwritten budget is a mood.
Enforcing it: the part everyone skips
A budget without a checkpoint is decoration. You need a moment where the number gets checked, and the cheapest reliable moment is before and after every meaningful change:
- The two-minute manual check. Before installing a plugin or theme update, load your homepage with DevTools' Network tab open and note total transferred bytes and request count. After, check again. The delta is the plugin's price tag, now visible. This costs two minutes and catches the majority of budget-killers.
- Scheduled audits. A monthly PageSpeed Insights run on your three most important page types (home, a post, a product/service page), with the numbers logged in a spreadsheet. Trends matter more than any single reading — lab numbers wobble; a three-month upward drift doesn't lie.
- Automated checks, if you have a build pipeline. Lighthouse CI accepts a budgets file and fails a build that exceeds it. For teams deploying through Git, this is the gold standard: nobody has to remember anything, and a pull request that blows the JavaScript budget simply doesn't go green. For a typical WordPress site updated through the admin, the manual and scheduled checks carry the weight instead.
- Field data as the backstop. The Chrome UX Report data shown in PageSpeed Insights reflects your real visitors over the trailing 28 days. Check it monthly. Lab tests catch regressions instantly; field data confirms whether they mattered.
When the budget is blown
Sooner or later a change you genuinely want will exceed the budget. There are exactly three honest responses, and they form the entire governance model:
- Optimize the newcomer. Can the widget load only on the pages that use it? Can it load on interaction (click-to-load chat is the classic example — most chat widgets can be replaced by a static button that loads the real widget on first click, cutting their cost to near zero for the majority who never chat)? Can the images ship in a modern format at sane dimensions?
- Pay for it by removing something else. The second font family, the slider nobody swipes, the social share buttons with their embedded SDKs, the analytics tool that duplicates another analytics tool. Every mature site carries passengers. A blown budget is the occasion to find them.
- Raise the budget — explicitly, on purpose, in writing. Sometimes the feature is worth it. Fine: that's a legitimate decision. The failure mode isn't raising the budget; it's exceeding it silently, which is just not having a budget while claiming to.
What's not on the list: "ignore it this once." Budgets die by exceptions the same way sites get slow — one reasonable decision at a time.
Start smaller than feels serious
If a full budget table feels like ceremony, start with exactly two numbers: total page weight and LCP on your homepage. Write them down. Check them when you change something. That's a functioning performance budget — modest, but real, and infinitely more effective than a sophisticated one you never look at. You can add line items when the first two have survived contact with a quarter of actual maintenance.
The site that stays fast isn't the one that got a heroic optimization sprint last year. It's the one where somebody, every month, quietly compares a number against a line and asks the new widget to justify itself. Budgets aren't exciting. That's the point — they make performance boring, routine, and durable, which is exactly what "fast" looks like from the inside.