Every kilobyte you ship has a cost. On a fast fiber connection it feels negligible, but on a mid-tier Android device over 4G, an extra 400KB of JavaScript can add 1.2 seconds to Time to Interactive and push Largest Contentful Paint past the 2.5s threshold. A CDN can make delivery faster, but it cannot fix an overweight page. That is where performance budgets come in.
A CDN performance budget is a set of explicit, measurable limits on what your edge is allowed to deliver — total page weight, image payload, JavaScript size, font count, and third-party overhead. When enforced correctly, budgets act as guardrails in CI/CD and at the edge, preventing regressions from ever reaching production. This guide shows how to set realistic limits and enforce them with CDN configuration, build tooling, and real-user monitoring.
What a CDN Performance Budget Actually Is
Unlike a generic performance budget that lives in a spreadsheet, a CDN performance budget is operational. It combines three layers:
- Transfer budget: Maximum bytes delivered over the wire per navigation (HTML + CSS + JS + images + fonts + XHR). This is what the user actually pays for.
- Asset-count budget: Limits on number of requests, domains, and third-party scripts. Request overhead matters as much as bytes on HTTP/2 and HTTP/3.
- Timing budget: Derived limits for Core Web Vitals — LCP, CLS, and INP — that your page weight budget must support.
Understanding how a CDN works is essential here. The edge can compress, resize, cache, and even block assets, but it does so based on rules you define. A budget translates business goals like “LCP under 2.0s on 75th percentile” into enforceable rules like “total image weight < 800KB, JS < 170KB gzipped, no render-blocking third parties.”
Why Page Weight Still Dictates Performance
Compression and edge caching have improved, yet median page weight continues to climb. According to HTTP Archive, the median mobile page now exceeds 2,400KB, with images accounting for ~45% and JavaScript ~23%. That weight has direct consequences:
| Metric | Edge Processing | Origin Processing | Improvement |
|---|---|---|---|
| Latency (p50) | 8–15 ms | 120–300 ms | 15–20x faster |
| Cache Hit Ratio | 85–95% | N/A | Reduces origin load |
| TLS Handshake | 1–5 ms (nearby PoP) | 50–150 ms | 10–30x faster |
| Bandwidth Cost | $0.01–0.04/GB | $0.05–0.12/GB | 3–5x cheaper |
| Availability | 99.99% (multi-PoP) | 99.9% (single DC) | 10x fewer outages |
- Bandwidth contention: Large payloads compete with critical resources. Even with efficient CDN caching, uncached HTML and dynamic API responses still block rendering.
- CPU cost: JavaScript weight correlates with parse and compile time. A 350KB bundle can cost 800ms of main-thread work on a Moto G4.
- Cache efficiency: Overweight pages bust edge caches faster and increase origin egress. Smaller, versioned assets have higher hit ratios.
For e-commerce and media sites, the impact is revenue. Walmart found that every 100ms improvement in load time increased revenue by 1%, and most of that gain came from reducing JavaScript and image weight — not from faster edge PoPs.
Setting Realistic Limits: The Budget Table
Do not copy budgets from generic blog posts. Base them on your Real User Monitoring (RUM) and your competitive baseline. Run WebPageTest on your top 5 templates (homepage, category, product, checkout, blog) across cable and 4G, then set budgets at the 75th percentile of your best-performing competitor minus 10-15%.
Use this starter framework and tighten it after two sprints of data:
| Budget Metric | Recommended Limit (Mobile) | Enforcement Point | Severity |
|---|---|---|---|
| Total Transfer Size | ≤ 1,700 KB (≤ 1,000 KB critical path) | CI + CDN log alert | Block |
| JavaScript (gzipped) | ≤ 170 KB total, ≤ 80 KB per route | Bundle analyzer + Edge worker | Block |
| Images (total) | ≤ 800 KB, ≤ 250 KB LCP image | CDN image optimization | Warn |
| CSS (gzipped) | ≤ 30 KB critical, ≤ 60 KB total | CI check | Warn |
| Fonts | ≤ 2 families, ≤ 80 KB, WOFF2 only | CDN header + preload | Warn |
| Third-Party Scripts | ≤ 3 sync, ≤ 150 KB total | CDN Content Security Policy | Audit |
| HTTP Requests | ≤ 50 (≤ 30 critical) | RUM + synthetic | Warn |
If you already use TLS and HTTP/3, you can be slightly more permissive on request count but stricter on bytes — multiplexing reduces handshake overhead but does not reduce parse cost.
Enforcing Budgets at the CDN Edge
CI is your first line of defense, but runtime enforcement is where CDN budgets prove their value. Users do not run your build — they hit your edge.
1. Define budgets as code
Store budgets in version control so every deploy is checked. Use Lighthouse CI or Sitespeed.io format:
// budget.json — enforced in CI and synced to CDN worker KV [ { "path": "/*", "resourceSizes": [ { "resourceType": "document", "budget": 75 }, { "resourceType": "script", "budget": 170 }, { "resourceType": "image", "budget": 800 }, { "resourceType": "stylesheet", "budget": 60 }, { "resourceType": "font", "budget": 80 }, { "resourceType": "total", "budget": 1700 } ], "resourceCounts": [ { "resourceType": "third-party", "budget": 6 } ] } ]
2. Configure edge optimizations
Most CDNs can enforce weight limits without custom code. Enable these policies in order of impact:
- Automatic image optimization: Polish, Image Resizing, or equivalent. Set quality to 75-80, force WebP/AVIF, and cap width at 1920px.
- Brotli + Gzip: Enable Brotli level 6 at edge, fallback to Gzip. Ensure
content-encodingis cached separately. - Font subsetting and display swap: Serve WOFF2 only, add
font-display: swapand cache fonts for 1 year with immutable. - Early Hints and priority: Use 103 Early Hints for LCP image and critical CSS.
3. Add an edge worker for hard limits
For strict budgets, deploy a lightweight worker that inspects responses and either optimizes or flags violations:
export default { async fetch(request, env) { const res = await fetch(request); const bytes = parseInt(res.headers.get('content-length') || '0', 10); const type = res.headers.get('content-type') || ''; // Enforce image budget: recompress if oversized if (type.startsWith('image/') && bytes > 250 * 1024) { return fetch(request, { cf: { image: { quality: 75, format: 'auto' } } }); } // Add budget header for observability res.headers.set('x-perf-budget', bytes > 1700*1024 ? 'over' : 'ok'); return res; } }
This pattern does not break the user experience — it gracefully degrades quality or adds an observability header that your logging pipeline can alert on.
CI Checks and Continuous Monitoring
A budget without automation is a suggestion. Wire it into your pipeline:
# .github/workflows/perf-budget.yml - name: Lighthouse CI with budgets run: | npm run build npx lhci autorun --config=./lighthouserc.json # lighthouserc.json asserts budgets and fails PR if exceeded { "assert": { "assertions": { "resource-summary:script:size": ["error", {"maxNumericValue": 170000}], "resource-summary:image:size": ["error", {"maxNumericValue": 800000}], "largest-contentful-paint": ["warn", {"maxNumericValue": 2500}] } } }
Beyond CI, monitor drift in production. CDN logs are the source of truth for delivered bytes — not your build folder. Create a daily job that aggregates content-length by route and compares it to budget. Alert in Slack when the 75th percentile exceeds 90% of budget for two consecutive days. Pair this with RUM for LCP and INP so you can correlate weight regressions with user impact.
Finally, make budgets visible. Add a performance dashboard to your internal docs, show budget status on every pull request, and review exceptions in a weekly perf council. Teams respect limits they can see.
Frequently Asked Questions
What is a good page weight budget for a CDN-delivered site?
For most content and e-commerce sites, aim for under 1,700KB total transfer on mobile and under 1,000KB for critical landing pages. Keep JavaScript under 170KB gzipped, CSS under 60KB, and images under 800KB per page. Tighten these numbers until your 75th percentile LCP is consistently under 2.5s.
How do CDNs enforce performance budgets?
CDNs enforce budgets through edge configuration: automatic image compression and format conversion, Brotli compression, cache policies, and edge workers that inspect response sizes. They can also inject headers for observability and trigger alerts or block deployments when thresholds are exceeded.
Should performance budgets block deployments?
Yes for hard violations like JavaScript or total weight overages above 10%. Configure Lighthouse CI or bundle-size checks to fail the build. For softer limits, use warnings and require approval. The key is to catch regressions before they reach the edge.
How often should you review CDN performance budgets?
Review quarterly and after any major redesign or third-party addition. Use RUM and CDN log data to adjust. As your site gets faster, lower the budget to prevent creep; only increase it with documented business justification and performance impact analysis.