BOOTING NEURAL FEED…
NEWSBOX v0.2 · NEON SPONSOR ↗
← WSZYSTKIE NEWSY
Tech & Dev 75% CONFIDENCE Dev.to Top 15 czerwca 2026 01:08

Performance Budgeting: Setting Targets and Automating Enforcement

AUTHOR · sweet

A performance budget is a set of agreed-upon thresholds that your application must not exceed — bundle size, load time, image weight, API latency. Without a budget, performance degrades incrementally with every feature added. This guide covers how to define, measure, and enforce performance budgets in CI/CD, with patterns used at tanstackship.com. Performance decays silently. Each feature adds JavaScript, images, and API calls. Individually, each addition is unnoticeable. Cumulatively, over 6-12 months, a page that loaded in 1.5 seconds becomes a 4-second page. Feature JS Added Latency Added C

A performance budget is a set of agreed-upon thresholds that your application must not exceed — bundle size, load time, image weight, API latency. Without a budget, performance degrades incrementally with every feature added. This guide covers how to define, measure, and enforce performance budgets in CI/CD, with patterns used at tanstackship.com . Why Performance Budgets Matter Performance decays silently. Each feature adds JavaScript, images, and API calls. Individually, each addition is unnoticeable. Cumulatively, over 6-12 months, a page that loaded in 1.5 seconds becomes a 4-second page. Feature JS Added Latency Added Cumulative (6 months) Analytics dashboard 18 KB +100ms +100ms Team collaboration 25 KB +200ms +300ms File upload UI 12 KB +80ms +380ms Data export 8 KB +50ms +430ms Chat integration 35 KB +300ms +730ms Without a budget, the 730ms cumulative increase goes unnoticed until users complain — or your Core Web Vitals score drops and SEO rankings fall. Defining Budgets Metric Categories // performance-budget.config.ts export const performanceBudget = { // Quantity budgets — tracked at build time javascript : { totalInitial : 150 * 1024 , // 150 KB (gzipped) routeLevel : 50 * 1024 , // 50 KB per route chunk }, css : { totalInitial : 30 * 1024 , // 30 KB criticalPath : 15 * 1024 , // 15 KB inlined }, images : { heroImage : 200 * 1024 , // 200 KB thumbnail : 50 * 1024 , // 50 KB totalPageWeight : 500 * 1024 , // 500 KB total maxImageCount : 15 , // Max images per page }, fonts : { total : 40 * 1024 , // 40 KB maxCustomFonts : 2 , // Max font families }, // Timing budgets — tracked in CI and RUM timing : { lcp : 2500 , // < 2.5s cls : 0.1 , // < 0.1 inp : 200 , // < 200ms ttfb : 800 , // < 800ms firstContentfulPaint : 1800 , // < 1.8s timeToInteractive : 3500 , // < 3.5s }, // Network budgets network : { totalRequests : 50 , // Max HTTP requests thirdPartyScripts : 5 , // Max third-party scripts blockingScripts : 0 , // No render-blocking scripts }, } CI/CD Enforcement with Lighthouse CI # .github/workflows/performance.yml name : Performance Budget on : pull_request : branches : [ main ] jobs : lighthouse : runs-on : ubuntu-latest steps : - uses : actions/checkout@v4 - uses : actions/setup-node@v4 - run : npm ci - run : npm run build - run : npm run start:preview & - name : Run Lighthouse CI run : | npm install -g @lhci/cli lhci autorun --config=lighthouserc.json - name : Check Bundle Size run : | npm run build -- --report node scripts/check-bundle-size.mjs ./dist/report.html - name : Check Image Budget run : | node scripts/check-image-budget.mjs ./dist/public - name : Comment PR on Failure if : failure() uses : actions/github-script@v6 with : script : | github.rest.issues.createComment({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, body: 'Performance budget check failed. See details in the workflow run.' }) Lighthouse CI Configuration { "ci" : { "collect" : { "numberOfRuns" : 3 , "staticDistDir" : "./dist/public" , "settings" : { "throttlingMethod" : "devtools" , "formFactor" : "desktop" } }, "assert" : { "assertions" : { "largest-contentful-paint" : [ "error" , { "maxNumericValue" : 2500 }], "cumulative-layout-shift" : [ "error" , { "maxNumericValue" : 0.1 }], "interaction-to-next-paint" : [ "error" , { "maxNumericValue" : 200 }], "total-blocking-time" : [ "error" , { "maxNumericValue" : 200 }], "max-potential-fid" : [ "warn" , { "maxNumericValue" : 100 }], "uses-responsive-images" : "error" , "offscreen-images" : "error" , "unminified-javascript" : "error" , "unminified-css" : "error" , "render-blocking-resources" : [ "warn" , { "maxLength" : 3 }] } }, "upload" : { "target" : "temporary-public-storage" } } } Bundle Size Enforcement // scripts/check-bundle-size.mjs import { readFile } from " fs/promises " import path from " path " const BUDGET = { " main " : 150 * 1024 , // Main entry point: 150KB " vendor " : 50 * 1024 , // Vendor chunk: 50KB } async fu

CZYTAJ ŹRÓDŁOWY ARTYKUŁ → WIĘCEJ Z TECH & DEV