Web Performance Budgets — Setting and Enforcing Limits
In this tutorial, you will learn how to set and enforce performance budgets to keep your web application fast as it grows. A performance budget defines maximum acceptable thresholds for metrics like page weight, LCP, TTI, and the number of HTTP requests. DodaTech uses performance budgets as guardrails, catching regressions before they reach production.
What You Will Learn
- How to define performance budgets for different metric types
- How to measure current performance and set realistic targets
- How to automate budget enforcement in CI/CD pipelines
- How to manage budget trade-offs with stakeholders
Why It Matters
Without a budget, performance degrades gradually as teams add features, images, and third-party scripts. A performance budget acts as an early warning system. DodaTech found that teams that enforced budgets had 40 percent fewer performance regressions than those that did not.
Real-World Use Case
The DodaZIP web app set a budget of LCP under 2.0 seconds and total page weight under 500KB. When a developer accidentally added a third-party charting library that increased bundle size by 300KB, the CI pipeline rejected the Pull Request, preventing a 60 percent page weight increase from reaching production.
Prerequisites
You should understand Core Web Vitals metrics and how to use Lighthouse Audits. Familiarity with CI/CD concepts and GitHub Actions is helpful.
Step-by-Step Tutorial
Step 1: Define Your Budget Metrics
A comprehensive performance budget covers three categories:
- Quantitative metrics: LCP under 2.5s, TBT under 200ms, CLS under 0.1
- Resource budgets: Total page weight under 500KB (gzipped), JavaScript under 200KB, images under 300KB
- Request budgets: Total HTTP requests under 30, third-party requests under 10
Document these in a shared location accessible to the whole team.
{
"performance": {
"lcp": { "max": 2500 },
"tbt": { "max": 200 },
"cls": { "max": 0.1 },
"si": { "max": 3000 }
},
"resources": {
"totalWeight": { "max": 500 },
"jsWeight": { "max": 200 },
"imageWeight": { "max": 250 },
"fontWeight": { "max": 50 },
"cssWeight": { "max": 50 }
},
"requests": {
"total": { "max": 30 },
"thirdParty": { "max": 10 }
}
}
Step 2: Measure Your Baseline
Run Lighthouse and gather metrics for your current production site. Use the median of five runs to establish a baseline.
# Gather baseline metrics with Lighthouse CI
npx lhci collect --url https://dodatech.com --numberOfRuns 5
npx lhci upload --target filesystem --outputDir ./lhci-data
Expected output: A directory with Lighthouse reports and a manifest file containing the median metrics for each URL.
Compare these baseline numbers against your budget. If the baseline already exceeds a budget, set an improvement budget (reduce by 10 percent, then 20 percent) rather than immediately enforcing the ideal target.
Step 3: Create a Lighthouse Budget File
Lighthouse supports a budget.json file that defines thresholds.
[
{
"path": "/*",
"resourceSizes": [
{"resourceType": "total", "budget": 500},
{"resourceType": "script", "budget": 200},
{"resourceType": "image", "budget": 250},
{"resourceType": "font", "budget": 50},
{"resourceType": "stylesheet", "budget": 50}
],
"resourceCounts": [
{"resourceType": "total", "budget": 30},
{"resourceType": "third-party", "budget": 10}
],
"timings": [
{"metric": "largest-contentful-paint", "budget": 2500},
{"metric": "total-blocking-time", "budget": 200},
{"metric": "cumulative-layout-shift", "budget": 0.1},
{"metric": "speed-index", "budget": 3000}
]
}
]
Step 4: Enforce Budgets with Lighthouse CI
Lighthouse CI compares Lighthouse results against the budget and exits with a non-zero code when budgets are exceeded.
# Run Lighthouse CI with budget enforcement
npx lhci autorun --config=./lighthouserc.js
// lighthouserc.js
module.exports = {
ci: {
collect: {
numberOfRuns: 3,
url: ['https://dodatech.com']
},
assert: {
budgetsFile: './budget.json',
assertions: {
'categories:performance': ['error', {minScore: 0.9}],
'resource-summary': ['error', {budgets: './budget.json'}]
}
},
upload: {
target: 'filesystem',
outputDir: './lhci-reports'
}
}
};
Expected behavior: If the page exceeds any budget, the command exits with code 1 and prints which budgets were exceeded.
Step 5: Integrate Budgets into CI/CD
Add the Lighthouse CI step to your Pull Request workflow.
# .github/workflows/performance.yml
name: Performance Budget Check
on: [pull_request]
jobs:
performance:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: Build
run: npm run build
- name: Run Lighthouse CI
run: npx lhci autorun --config=./lighthouserc.js
env:
LHCI_GITHUB_APP_TOKEN: ${{ secrets.LHCI_GITHUB_APP_TOKEN }}
Expected behavior: The check shows a green checkmark if all budgets pass, or a red X with a detailed breakdown of which budgets were exceeded.
Step 6: Monitor Budget Over Time
Track budget compliance with a dashboard that shows trends over time.
# Export Lighthouse CI results for dashboarding
npx lhci collect --url https://dodatech.com --numberOfRuns 3
npx lhci upload --target filesystem --outputDir ./lhci-data
// Parse results for custom dashboard
const fs = require('fs');
const reports = fs.readdirSync('./lhci-data')
.filter(f => f.endsWith('.json'))
.map(f => JSON.parse(fs.readFileSync(`./lhci-data/${f}`)));
Step 7: Set Improvement Budgets
When your site already exceeds budgets, set improvement budgets that progressively tighten over time.
// Improvement budget - tighten by 10% per quarter
{
"timings": [
{"metric": "largest-contentful-paint", "budget": 3000},
{"metric": "total-blocking-time", "budget": 350}
]
}
Each quarter, reduce the budget by 10 percent until you reach the ideal target. This makes performance improvement manageable and sustainable.
Step 8: Communicate Budgets to the Team
Performance budgets are only effective if the team understands and accepts them. Document the rationale and revisit budgets quarterly.
# Performance Budgets — Q3 2026
| Metric | Budget | Current | Status |
|--------|--------|---------|--------|
| LCP | 2.5s | 1.8s | Pass |
| TBT | 200ms | 150ms | Pass |
| CLS | 0.1 | 0.05 | Pass |
| JS Weight | 200KB | 185KB | Pass |
| Page Weight | 500KB | 420KB | Pass |
Learning Path
flowchart LR A[Lighthouse Audits] --> B[Performance Budgets] B --> C[CI/CD Integration] B --> D[Bundle Optimization] C --> E[Real User Monitoring] D --> E style B fill:#4f46e5,color:#fff style A fill:#6366f1,color:#fff style C fill:#6366f1,color:#fff
Common Errors
Setting unrealistic budgets: Budgets that are too aggressive get ignored or cause teams to game the system. Start with a 20 percent improvement over baseline.
Only checking budgets in production: By the time a regression reaches production, it may already affect users. Check budgets in PR preview deployments or staging.
Ignoring mobile-specific budgets: Mobile devices have less CPU and memory. Set separate budgets for mobile with tighter thresholds.
Not updating budgets as the site evolves: Budgets that stay static for years become irrelevant. Revisit budgets quarterly and adjust based on actual data.
Budgeting only JavaScript weight: JavaScript weight is important, but images, fonts, and third-party scripts often contribute more to page weight. Include all resource types.
No stakeholder buy-in: Budgets that are not accepted by product managers and designers will be ignored. Involve the whole team in setting and reviewing budgets.
Practice Questions
- What is a performance budget and why is it important?
- Name three types of metrics that should be included in a performance budget.
- How does Lighthouse CI enforce performance budgets?
- What is an improvement budget?
- Why should budgets be revisited quarterly?
Answers: 1. A set of maximum thresholds for performance metrics that acts as a guardrail against regressions. 2. Timing metrics (LCP, TBT, CLS), resource sizes (JS, CSS, images), and request counts (total, third-party). 3. It runs Lighthouse, compares results against a budget.json file, and fails the build if any budget is exceeded. 4. A budget that progressively tightens over time, used when the current performance is already above the ideal target. 5. Sites evolve with new features and dependencies; budgets need to adapt while keeping performance goals aligned with business priorities.
Challenge
Create a performance budget for a sample e-commerce product page. Include budgets for LCP, TBT, CLS, total page weight, JavaScript weight, image weight, and total HTTP requests. Set up a Lighthouse CI configuration that enforces these budgets and integrate it with a GitHub Actions workflow. Test by intentionally adding a heavy library and verifying that the CI pipeline rejects it.
FAQ
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro