Set Performance Budgets That Protect Real Users
This guide shows you how to set performance budgets that go beyond lab-based metrics and focus on what real users actually experience. You’ll learn how to define budgets for Core Web Vitals, enforce them in your workflow, and adjust them based on field data from actual visitors. No prior experience with performance monitoring is needed, but basic familiarity with web development and analytics helps.
What You’ll Need
- Access to your website’s analytics (e.g., Google Analytics, Adobe Analytics, or a privacy-friendly alternative).
- A way to collect field data: either the Chrome User Experience Report (CrUX) for public sites, or a Real User Monitoring (RUM) tool like SpeedCurve, Request Metrics, or a self-hosted solution.
- A place to document budgets: a spreadsheet, a markdown file, or a dedicated performance budget tool.
- If you want to enforce budgets in CI/CD, access to your build pipeline (e.g., GitHub Actions, Jenkins, CircleCI).
- Basic knowledge of HTML, CSS, and JavaScript is helpful but not required.
Step-by-Step
-
Collect baseline field data for your key pages.
Start by gathering real user data for the pages that matter most: your homepage, product pages, article pages, or any page that drives conversions. Use CrUX (if your site is public) or your RUM tool to get the 75th percentile values for LCP, INP, and CLS. Record these numbers for at least 28 days to smooth out weekly variations.
-
Define your budget targets based on user impact.
Don’t just copy Google’s recommended thresholds. Set budgets that reflect your users’ context. For example, if your audience is on low-end mobile devices, you might set a stricter LCP budget (e.g., 2.0s) than the 2.5s threshold. Similarly, if your site is content-heavy, a CLS budget of 0.05 might be more appropriate than 0.1. Use the 75th percentile from your field data as a starting point, then aim to improve by 10-20%.
-
Choose the right metrics to budget.
Focus on Core Web Vitals (LCP, INP, CLS) because they directly affect user experience and search ranking. But also consider secondary metrics like TTFB (Time to First Byte), FCP (First Contentful Paint), and TBT (Total Blocking Time) if they are causing issues. For each metric, decide whether you’ll budget for the 75th percentile, the 90th percentile, or both. The 75th is standard, but the 90th catches the worst experiences.
-
Set budgets for both lab and field.
Lab data (from Lighthouse or WebPageTest) is reproducible and useful for catching regressions before they hit production. Field data is what real users experience. Set budgets for both: for example, a lab LCP of 2.0s (on a mid-range device) and a field LCP of 2.5s at the 75th percentile. This way you catch issues in development and verify them in production.
-
Document your budgets in a central place.
Create a table with columns: page template, metric, budget value, percentile, and source (lab or field). Store it in your repo (e.g.,
performance-budgets.md) or in a shared spreadsheet. Make it visible to your team. This becomes your single source of truth. -
Integrate budgets into your CI/CD pipeline.
Use tools like Lighthouse CI or a custom script to run performance tests on every pull request. Set the budgets so that the build fails if a metric exceeds the threshold. For example, if your LCP budget is 2.5s, the test will fail if LCP is 3.0s. This prevents regressions from being merged. Start with a “warn” level for a week to avoid blocking, then switch to “error” once the team is comfortable.
-
Monitor field data continuously.
Set up alerts in your RUM tool or CrUX API to notify you when a metric crosses your budget. For example, get an email or Slack message when the 75th percentile LCP exceeds 2.5s for two consecutive days. This helps you respond quickly to regressions caused by third-party scripts, new features, or changes in user traffic.
-
Review and adjust budgets quarterly.
Performance is not static. As you optimize, your field data will improve. Review your budgets every 3 months. If you are consistently under budget, tighten it further. If you are missing targets, either optimize or, if the target is unrealistic for your current setup, adjust it based on data—but only after you’ve made a genuine effort to improve.
Common Mistakes
- Only using lab data. Lab tests run on a controlled device and network, which often doesn’t match real user conditions. Field data is essential because it captures actual device performance, network types, and user interactions.
- Setting a single budget for all pages. Different page types have different requirements. A product page with a large hero image will have a different LCP than a text article. Budget per template, not globally.
- Ignoring the 90th percentile. The 75th percentile is the median experience, but the 90th percentile shows the worst-case. If your 90th is terrible, you’re still failing many users.
- Not involving the whole team. Performance is not just an engineering concern. Designers and content creators need to know that a huge hero image or a heavy font will break the budget.
- Setting budgets but not enforcing them. A budget that isn’t checked in CI is just a suggestion. Make it a hard gate.
Tips
- Start with the 75th percentile, then add the 90th. The 75th is the standard, but the 90th catches the worst experiences.
- Use a RUM tool that integrates with your stack. Tools like SpeedCurve or Request Metrics can tie field data back to specific releases, making it easier to spot regressions.
- Budget for the “page weight” as a proxy. If you don’t have RUM yet, set a budget on total page weight (e.g., <1MB on mobile) and number of requests (<50). It's not perfect, but it's a good start.
- Make budgets visible to everyone. Add a badge to your README or a dashboard on your team’s monitor.
- Automate alerts, but don’t alert on every dip. Use a threshold like “2 consecutive days above budget” to avoid noise.
Troubleshooting
Your CI test is failing but you think the change is fine. First, check if the lab environment is consistent. Use a fixed device (e.g., a mid-range Android phone) and network throttling (e.g., 4G). If the lab is fine, check field data—maybe the regression is only in production due to a third-party script. If it’s a false positive, adjust the test to use a more stable metric (e.g., use LCP instead of Speed Index).
Field data is not improving even after optimizations. Field data is lagging—it takes 28 days for CrUX to update. Also, check if the optimization is actually reaching users (e.g., are you caching correctly?). Use a RUM tool to see the distribution: maybe the 75th is improving but the 90th is not, meaning some users are still on slow connections.
You are constantly breaking the budget and the team is frustrated. Re-evaluate your budgets. If you set them too aggressive, it will cause friction. Instead of failing the build, start with a warning for a month, then gradually tighten. Or split budgets by page type—maybe the homepage is easier than a complex app page.
Your RUM tool shows different numbers than CrUX. This is normal because CrUX samples a broader audience and uses a 28-day window. Your RUM might be opt-in and may not include all users. Use both: CrUX for a baseline, your RUM for real-time alerts.
You don’t have any field data because your site is new. Use lab data with a realistic mid-range device and 4G throttling. Once you have enough traffic (a few thousand visits), start collecting field data. In the meantime, set budgets based on industry benchmarks, but be prepared to adjust.
Frequently Asked Questions
What is the difference between lab data and field data?
Lab data is collected in a controlled environment (e.g., Lighthouse on a simulated device). Field data comes from real users visiting your site, capturing their actual device, network, and interaction. Both are useful: lab for catching regressions early, field for understanding real user experience.
Should I budget for the 75th or 90th percentile?
Start with the 75th percentile because it represents the majority of users. But also track the 90th to catch the worst experiences. If your 90th is much worse, you may need to optimize for low-end devices or slower networks.
How often should I update my performance budgets?
Review them quarterly. If you are consistently under budget, tighten them. If you are missing them, either optimize or adjust if the target was unrealistic. But always base changes on data, not guesswork.
Can I use the same budget for desktop and mobile?
No. Mobile users are often on slower networks and less powerful devices. Set separate budgets for mobile and desktop, and even for different device classes (e.g., low-end vs. high-end).
What if my site is a single-page app (SPA)?
SPAs have unique challenges. For LCP, track the time to render the main content, not just the initial HTML. For INP, monitor event handler delays. Use a RUM tool that supports SPA route changes. Budgets should be per route, not just the initial load.
How do I get started if I don’t have a RUM tool?
Use the Chrome User Experience Report (CrUX) via PageSpeed Insights or the CrUX API. It gives you field data for your origin and URLs. For more granular data, install a lightweight RUM script (e.g., a custom script using the PerformanceObserver API) that sends data to your analytics.
Related
Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.