Establishing Performance Budgets: Preventing Regressions in React
Learn how to define a Performance Budget, set Core Web Vitals targets, and automate regression testing using Lighthouse CI to keep your React app fast.
Previously in this course, we explored Profiling with React DevTools to understand how and why components re-render. While profiling helps us fix specific bottlenecks, it is a manual, reactive process. To scale performance, we must move from reactive debugging to proactive governance.
This lesson introduces the Performance Budget—a set of quantitative constraints that define the acceptable limits for your application's performance. Without these, performance is just a "nice to have" that inevitably degrades as features accumulate.
Defining Your Core Web Vitals Targets
A Performance Budget isn't just about total bundle size; it’s about user experience. We use Core Web Vitals as our primary North Star metrics because they correlate directly with real-world user satisfaction.
For our project, we will adopt the "Good" thresholds defined by Google:
| Metric | Target (Desktop/Mobile) | What it represents |
|---|---|---|
| LCP | < 2.5s | Loading performance |
| INP | < 200ms | Interactivity |
| CLS | < 0.1 | Visual stability |
If you haven't yet implemented tracking, consider Core Web Vitals tracking: Implementing Reliable RUM with Beacon API to validate these targets against real user data rather than just synthetic lab environments.
Establishing a Baseline Audit
Before we enforce limits, we need to know where we stand. Run an initial audit using the Lighthouse CLI to generate a baseline.
Bash# Install Lighthouse npm install -g lighthouse # Run a baseline audit on your local dev server lighthouse http://localhost:3000 --view --output-path=./performance-baseline.html
Open the generated performance-baseline.html. Note your scores. If your LCP or CLS are failing, do not set the budget to your current (bad) score. Set it to the "Good" threshold. This forces you to optimize immediately to pass the build, rather than accepting poor performance as the new normal.
Integrating Lighthouse CI
To prevent future regressions, we integrate Performance Budgets: Automating Regression Testing with Lighthouse CI. This turns your performance budget into a "fail-fast" gate in your CI/CD pipeline.
-
Install the CLI:
npm install --save-dev @lhci/cli -
Create
lighthouserc.jsin your root:JAVASCRIPTmodule.exports = { ci: { assert: { preset: CE9178">'lighthouse:recommended', assertions: { CE9178">'largest-contentful-paint': [CE9178">'error', { minScore: 0.9 }], CE9178">'cumulative-layout-shift': [CE9178">'error', { minScore: 0.9 }], CE9178">'interactive': [CE9178">'error', { minScore: 0.9 }], CE9178">'total-byte-weight': [CE9178">'error', { maxNumericValue: 500000 }], // 500KB limit }, }, }, }; -
Add to your CI pipeline: In your GitHub Actions or GitLab CI file, add a step to run
lhci autorun. This will spin up your app, run Lighthouse, and fail the build if your budget is exceeded.
Hands-on Exercise
- Baseline: Run the Lighthouse CLI on your current project. Record your LCP and CLS values.
- Budgeting: Update your
lighthouserc.jsto set atotal-byte-weightbudget. Start with a value 20% higher than your current bundle size. - Regression: Intentionally add a large dependency or a blocking script to your
App.js. Run your CI script locally to confirm that the build fails.
Common Pitfalls
- The "Flaky Score" Trap: Synthetic tests are sensitive to machine load. Always run your CI audits in a clean, consistent environment (e.g., a dedicated Docker container) rather than on a developer's laptop.
- Budgeting for "Perfect": Avoid setting budgets to 100/100. It leads to developer burnout and encourages "gaming" the audit rather than optimizing the user experience. Aim for "Good" thresholds.
- Ignoring Mobile: Always audit on a simulated mobile device. Desktop scores often mask severe performance issues that plague users on mid-range mobile hardware.
Recap
We've established that performance is a feature, not an afterthought. By setting Core Web Vitals targets, establishing a baseline, and using Lighthouse CI to enforce budgets, we ensure that our performance gains aren't eroded by future code changes.
Up next: We will dive into Strategic use of React.memo to begin optimizing our component tree based on the bottlenecks identified in our initial profiling.
Work with me

Next.js Full-Stack Web App Development
A fast, SEO-ready full-stack web app built with Next.js 16 — from idea to deployed product, by an engineer who ships to production.

Headless WordPress + Next.js Frontend Development
Keep WordPress for content, get a lightning-fast Next.js frontend. The best of both worlds — familiar editing, modern speed.