Guides

Performance Guide

How to Build a Web Performance Budget That Teams Actually Use

A performance budget is not a number in a spreadsheet. It is a release contract that connects user experience, technical limits, ownership, and a safe response when the limit is exceeded.

A useful performance budget answers one question before a feature ships: what are we willing to spend for this experience, and what will we remove or improve when we reach the limit? The budget can cover page weight, JavaScript, images, requests, third parties, timings, and field metrics. The exact values must come from your product, traffic, devices, and baseline, not from a universal score.

The most durable approach combines two views. Lab and build budgets protect the inputs teams control. Field budgets protect the experience real users receive. Google recommends evaluating Core Web Vitals in the field at the 75th percentile: LCP at or below 2.5 seconds, INP at or below 200 milliseconds, and CLS at or below 0.1 for a good experience. These are useful reference thresholds, but a product team may choose stricter targets for a critical journey or different guardrails for a media-heavy page.

Build the budget in six steps

1. Start with a business journey

Do not create one budget for an entire site. A marketing landing page, product detail page, search results page, article, and checkout have different content and interaction requirements. Choose two or three page archetypes first. For each, write the user action the page must support, the business metric it influences, and the experience that must not regress.

Give every budget a named owner. Product decides what experience is worth protecting. Design decides what is essential. Engineering decides how to implement it. Platform or operations owns delivery and monitoring. Without an owner, an over-budget result becomes an observation instead of a decision.

2. Establish a baseline you can reproduce

Capture a representative release in a production-like environment. Measure a clean build and a deployed page. Record compressed and uncompressed asset sizes, request counts, third-party origins, response timing, LCP, CLS, and lab interaction proxies such as TBT. Then collect field data by page type, device, region, and release version.

Use multiple runs and report a range rather than one lucky result. A cold-cache lab test and a returning-user visit answer different questions. RUM versus synthetic monitoring explains how to keep those signals distinct while using both.

3. Choose a small set of limits

Start with limits that map to decisions. A generic example might include:

Budget dimensionExample starting limitOwnerEnforcement
Compressed JavaScript on mobile200 KBFrontendBuild check
Critical images on a product page500 KBDesign and contentAsset check
Third-party origins8Product and marketingReview gate
Total page transfer1.5 MBEngineeringLab check
75th percentile LCP2.5 s or betterPlatformRUM dashboard
75th percentile INP200 ms or betterFrontendRUM dashboard

These values are illustrative, not Optimi targets or a promise for every site. Set the first budget close enough to the baseline that the team can make progress, then tighten it when the delivery process is stable. Keep resource limits separate from user-centric metrics: a page can fit under a byte limit and still render the critical content late.

4. Put checks where the failure can be fixed

Build-time checks are fast and precise for bundles, images, fonts, and generated HTML. A deployed lab check catches dynamic resources, CDN headers, cache behaviour, and the actual network path. A RUM check catches real-world variation after release. Use each at the layer it can observe.

Lighthouse supports budget files for timing, resource sizes, and resource counts. A generic shape looks like this:

[
  {
    "path": "/*",
    "resourceSizes": [
      { "resourceType": "script", "budget": 200 },
      { "resourceType": "total", "budget": 1500 }
    ],
    "resourceCounts": [
      { "resourceType": "third-party", "budget": 8 }
    ]
  }
]

Treat the units and supported metric names as tool configuration, not as a portable standard. Pin the test browser, URL set, network profile, and Lighthouse version enough to make changes comparable. Store reports as CI artifacts so a failed check explains which resource or timing crossed the limit.

5. Make exceptions explicit

Budgets should not block legitimate work without a path forward. Require an exception record with the feature, cost, reason, owner, expiry date, and mitigation. For example, a new payment provider may add a third party, but the team can defer it, load it after interaction, and set a review date. An exception without an expiry is simply a permanent budget increase.

Review the budget when the page archetype changes, a new market or device segment becomes important, or field data shows that the limit no longer predicts experience. Do not silently move the baseline to make a regression look healthy.

6. Connect the budget to operations

A release can pass CI and still become slow after a cache change, origin incident, or regional routing issue. Monitor field metrics by release, template, geography, device, and CDN path. Track response errors and cache-hit behaviour alongside browser metrics. For managed CDN delivery, delivery policy is part of the budget. For Multi CDN, compare providers rather than hiding them in one global number.

When a live budget is exceeded, define a rollback ladder: disable the feature flag, restore the previous asset or release, revert the edge rule, or shift traffic to a known-good delivery path. A budget is useful because it makes the rollback decision earlier and less political.

A budget is a decision rule

The important question is not whether a page is over by one kilobyte. It is whether the team knows who owns the tradeoff, what evidence justifies the exception, and which reversible action restores the experience.

Common mistakes

  • Setting one site-wide number for pages with fundamentally different jobs.
  • Measuring only Lighthouse and never checking real users.
  • Using a performance score as the only budget.
  • Budgeting total bytes but ignoring critical-path order and main-thread work.
  • Allowing third-party scripts without a named owner or removal date.
  • Failing a pull request without an artifact that shows what changed.
  • Raising the limit after every failure instead of fixing or documenting the tradeoff.
  • Forgetting edge cache, origin latency, and regional delivery when setting a browser budget.

Read Technical SEO/GEO when response time and crawl efficiency are part of the goal. See the CDN migration guide before changing delivery infrastructure, and contact Optimi when you need to turn a multi-region performance baseline into an operating model.

There are only two hard things in Computer Science: cache invalidation and naming things.

Turn performance goals into a release contract

Talk to our team about baselines, budgets, observability, and safer delivery decisions.

Contact Optimi