Performance Budgets
performance budgets performance budgets operationalize core web vitals and crp constraints as ci-enf performance budgets are enforceable limits on metrics
Introduction
Performance budgets are enforceable limits on metrics and resources — max LCP milliseconds, max JS kilobytes in HTML, max CLS score — that fail CI builds when exceeded. The Chrome team and web.dev advocate budgets tied to Core Web Vitals thresholds and CrUX p75 targets, not arbitrary Lighthouse score gamification.
Budgets translate CWV from dashboard charts into merge-blocking contracts between design, marketing, and platform engineering.
Business problem
Business pressure: Without budgets, each squad adds one script tag to shared HTML shell — death by thousand cuts. After 18 months, origin CrUX LCP p75 crossed from Good to Poor; no single team owned regression. Budgets assign accountability before merge, not after quarterly CrUX review.
- Conversion: Budget for checkout HTML weight prevents accidental 400KB script addition blocking INP.
- Compliance: Budget for CLS on form templates protects motor-impaired users from shift regressions.
- SEO: Budget thresholds aligned to CrUX Good bands — proactive vs reactive Search Console firefighting.
Why this feature exists
Platform motivation: Performance regressions are gradual — budgets detect slope before cliff. Tim Kadlec and Google perf advocates formalized budget types: quantity (KB), rule (no sync scripts), and metric (LCP < 2500ms).
- History: Early weight limits → Lighthouse CI budgets → CWV-metric budgets post-2020.
- Alternative rejected: Post-release manual audit — always too late for busy teams.
- Modern role: Speedometer 3, Lighthouse 12+, and custom PerformanceObserver assertions in CI.
Browser internals
Inside the engine: Budgets proxy engine work — JS KB correlates with parse/compile/INP; blocking CSS count correlates with CRP length; DOM node count correlates with style recalc. Metric budgets (LCP, CLS, INP) simulate engine output on reference device in lab CI.
- Quantity budgets: transferSize of scripts/styles/images in network trace.
- Metric budgets: Lighthouse audit values matching web.dev CWV thresholds.
- Custom budgets: DOM size, third-party count, long task count in trace.
- Field budgets: RUM alert thresholds below CrUX Good — early warning before Search impact.
lighthouseci assert--preset=desktop--assertions.categories.performance=error--assertions.largest-contentful-paint=error:2500--assertions.cumulative-layout-shift=error:0.1--assertions.interaction-to-next-paint=error:200--assertions.resource-summary.script.size=error:300000
Rendering workflow
Rendering path: Budgets map to CRP stages — head script budget protects tokenization; CSS budget protects CSSOM gate; image budget protects LCP load; long task budget protects INP presentation delay.
- Critical path: Budget max render-blocking resources in head HTML.
- Layout: Budget max DOM depth/nodes on listing templates.
- Paint: Budget max web font files and weight.
Feature deep dive
Budget types per web.dev performance budget guide: (1) Metric — LCP, INP, CLS, TTFB; (2) Resource — JS, CSS, image, font KB; (3) Rule — no document.write, no sync script in head, img must have dimensions.
- Start point: Current CrUX p75 minus 10% headroom — achievable improvement target.
- Scope: Per template — homepage, PLP, PDP, checkout — not one global number.
- Enforcement: Lighthouse CI on PR; optional RUM canary alert post-deploy.
- Exceptions: ADR required to exceed budget — temporary with expiry date.
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Budget-Friendly Page</title><style>body { font-family: system-ui; margin: 2rem; max-width: 40rem; }.badge { background: #e6f4ea; padding: 0.5rem 1rem; border-radius: 4px; }</style></head><body><h1>Performance Budget Example</h1><p class="badge">Target: LCP < 2.5s · INP < 200ms · CLS < 0.1 · JS < 300KB</p><img src="https://picsum.photos/400/200" width="400" height="200" alt="Sized hero"><p>Minimal HTML, sized image, no blocking scripts — budget-friendly shell.</p></body></html>
Accessibility analysis
A11y architecture: Budget for focusable element count and modal DOM complexity — large DOM hurts INP for keyboard users traversing many controls.
- Screen readers: Limit live region spam — INP and cognitive load.
- Keyboard: Tab stop budget on single page — architectural review trigger.
- WCAG: Perf is accessibility — budget protects low-end device users.
SEO impact
SEO architecture: Budget thresholds set to CrUX Good values ensure deploy pipeline prevents Search Console CWV degradation 28 days later. SEO signs off on budget exceptions affecting landing templates.
- Crawl: HTML weight budget speeds TTFB and parse — indirect crawl efficiency.
- Rich results: Template budget includes JSON-LD size and inline critical HTML for schema visibility.
- Core Web Vitals: Budget IS the operationalization of CWV for engineering.
Security considerations
Security boundary: Third-party script budget limits tag manager proliferation — reduces XSS supply chain and INP risk simultaneously.
- XSS: Fewer inline scripts satisfies CSP and script count budget.
- CSP: Budget pairs with script allowlist — new vendor requires budget slot.
- Clickjacking: iframe embed budget limits overlay attack surface.
Performance impact
Performance: Budgets are the performance strategy — web.dev, CrUX targets, and Lighthouse CI implement them. Without enforcement, perf docs are ignored under release pressure.
- LCP: Budget LCP < 2.5s lab mobile on key URLs.
- INP: Budget long tasks < 3 per interaction trace in CI.
- CLS: Budget CLS < 0.1 lab; RUM alert at 0.08.
Real production example
Production pattern: Financial Times documented perf budget culture — max page weight, max ads, metric thresholds in CI. When budget exceeded, feature ships disabled until optimized — referenced in Google I/O perf sessions and web.dev budget articles.
- Pattern: bundlesize or Lighthouse CI in GitHub Actions; PR comment shows delta.
- Monitoring: RUM weekly report vs budget; CrUX monthly executive review.
- Fix: Marketing tag moved over budget — deferred load until interaction — budget green, INP improved.
Enterprise usage
Enterprise: Platform team owns golden template budgets; product teams request budget allocation for new features. Perf council approves exceptions with CrUX impact estimate.
- Design system: Component JS/CSS size documented — sums to page budget.
- CMS: Publish pipeline rejects images over 200KB without approval.
- CI gates: Monorepo path-filtered Lighthouse on affected templates only.
Common production failures
What breaks in prod: Budget defined but warn-only — team ignored warnings for 6 months until CrUX Poor. Warn-only budgets are worthless under deadline pressure — must fail build.
- Incident: Budget checked desktop only — mobile CrUX failed while CI green.
- SEO regression: Black Friday feature bypassed budget "temporarily" — never reverted.
- Perf regression: Budget tracked total JS but not third-party subset — tag manager hid growth.
Architecture review questions
- Do we have written budgets per template for LCP, INP, CLS, JS KB?
- Are budgets enforced as CI errors or warnings?
- Do mobile lab settings match CrUX device class we fail on?
- Is there an exception process with ADR and expiry?
- Do budgets include HTML rules (img dimensions, no sync head scripts)?
- Weekly: budget utilization trend — approaching limits before breach?
Hands-on project
Project: Define performance budget for one template aligned to web.dev Good thresholds. Add Lighthouse CI assert to repo. Intentionally regress (add 500KB script) and confirm CI fails.
- Deliverable: lighthouserc.json or assert script + failed CI screenshot.
- Verify: web.dev performance budget documentation.
- Stretch: Add custom budget for img missing width/height via HTML linter.
Interview questions
What types of performance budgets exist?(Intermediate)
Metric (LCP, INP, CLS, TTFB), resource (JS/CSS/font/image KB), and rule-based (no sync scripts, require img dimensions). web.dev recommends starting from current CrUX baseline. Enforce in Lighthouse CI.
Follow-up: Metric vs weight budget?
How do you set budget thresholds?(Advanced)
Align to Core Web Vitals Good values from web.dev: LCP 2500ms, INP 200ms, CLS 0.1. Use current CrUX p75 as baseline; tighten gradually. Per-template not site-wide. Include mobile lab device matching field failures.
Follow-up: How handle legitimate exceptions?
Budgets green but CrUX Poor — what failed?(Advanced)
Lab device/network mismatch; missing templates in CI; third parties load only in prod; geographic variance; 28-day lag. Add RUM alerts; expand CI URL coverage; use CrUX History to correlate deploy dates.
Follow-up: Desktop vs mobile budget?
Try it yourself
Edit the HTML, CSS, or JS panels — the preview updates as you type.
Try it yourself
Summary
Performance budgets operationalize Core Web Vitals and CRP constraints as CI-enforceable limits. Chrome team web.dev guidance and CrUX targets define thresholds; RUM validates budgets survive production diversity.