Core Web Vitals Budget Management Guide
An operating method that blocks performance regression at the release stage by budgeting LCP, INP, and CLS targets

Introduction
Many teams manage Core Web Vitals solely as a “monitoring metric.” So there are numbers on the dashboard, but they are not reflected in release decisions. As a result, performance regressions are discovered after deployment, and fixes are always deprioritized.
The purpose of this article is to suggest how to operate performance goals like a budget. The key is not to look at the indicators, but to control distribution based on the indicators.

Problem definition
Typical patterns in which performance operations fail are as follows:
- There are LCP/INP/CLS goals, but there is no responsible entity for each service/page.
- When experimental features are added, there is no performance impact verification at the PR stage.
- Even though the dashboard numbers look good, the long-tail, in which only certain paths deteriorate, is hidden.
- When a regression occurs, there is no rollback standard, so response is slow.
In conclusion, there is only “visibility of indicators” and no “executive power of indicators.”
Key concepts
| Item | Operational Questions | Recommended method |
|---|---|---|
| Budget definition | At what value will distribution be prevented | Specify threshold for each LCP/INP/CLS page |
| Measurement location | Where to measure | Lab + RUM Dual Measurement |
| Judgment criteria | What section to evaluate | p75 + simultaneous check of minimum number of samples |
| Response Strategy | What to do when the threshold is exceeded | Auto Alert + Step Rollback |
When budgeting metrics, “page/feature-specific goals” are more effective than “single global goals.”
Code Example 1: Setting a Performance Budget (JSON)
{
"budgets": [
{
"path": "/",
"lcp_ms_p75": 2500,
"inp_ms_p75": 200,
"cls_p75": 0.1
},
{
"path": "/posts",
"lcp_ms_p75": 2300,
"inp_ms_p75": 180,
"cls_p75": 0.08
},
{
"path": "/posts/[slug]",
"lcp_ms_p75": 2400,
"inp_ms_p75": 200,
"cls_p75": 0.1
}
]
}
Code example 2: CI gate script
import fs from "node:fs";
type Budget = {
path: string;
lcp_ms_p75: number;
inp_ms_p75: number;
cls_p75: number;
};
const budgets: Budget[] = JSON.parse(fs.readFileSync("./performance-budget.json", "utf8")).budgets;
const latest = JSON.parse(fs.readFileSync("./artifacts/web-vitals.json", "utf8"));
const failures = budgets.flatMap((budget) => {
const row = latest.find((item: any) => item.path === budget.path);
if (!row) return [`missing metrics: ${budget.path}`];
const issues: string[] = [];
if (row.lcp_ms_p75 > budget.lcp_ms_p75) issues.push(`${budget.path} LCP exceeded`);
if (row.inp_ms_p75 > budget.inp_ms_p75) issues.push(`${budget.path} INP exceeded`);
if (row.cls_p75 > budget.cls_p75) issues.push(`${budget.path} CLS exceeded`);
return issues;
});
if (failures.length > 0) {
console.error(failures.join("\n"));
process.exit(1);
}
Architecture flow
Tradeoffs
- If the budget gate is set strongly, the speed of distribution may slow down.
- Instead, performance regression can be changed to proactive blocking rather than reactive response.
- If the threshold is set too tightly in the beginning, team fatigue increases. It is best to readjust realistic standards every two weeks.
Cleanup
The key to running Core Web Vitals is not “good numbers” but “controllable release processes.” If the performance budget is defined in writing and executed in CI, performance is managed through a team system rather than individual capabilities.
Image source
- Cover: source link
- License: CC BY-SA 3.0 / Author: Wikimedia Foundation
- Note: After downloading the free license image from Wikimedia Commons, it was optimized to JPG at 1600px.