Static assets served from CDN with geographic edge caching
Why it matters
An origin server in us-east-1 adds 150–300ms of network latency for users in APAC or Europe before a single byte of content arrives (ISO-25010 time-behaviour). A CDN with geographic edge caching eliminates that latency by serving cached responses from the PoP nearest the user. Separately, static assets served without Cache-Control: immutable, max-age=31536000 are re-validated on every visit, incurring a conditional request round-trip even when the asset has not changed. Both issues compound on high-traffic pages.
Severity rationale
Info because CDN and cache-control gaps are genuinely harmful at scale but commonly resolved automatically by modern hosting platforms, making the finding most relevant to custom or self-hosted deployments.
Remediation
Configure aggressive cache headers for versioned static assets in next.config.ts:
// next.config.ts
const config = {
async headers() {
return [
{
source: '/_next/static/:path*',
headers: [
{
key: 'Cache-Control',
value: 'public, max-age=31536000, immutable'
}
]
}
]
}
}
export default config
Verify CDN is active by checking response headers for a CDN-specific header:
curl -sI https://yoursite.com | grep -i 'x-vercel-cache\|cf-cache-status\|x-cache'
# HIT = served from CDN edge; MISS = reached origin
For self-hosted deployments without a built-in CDN, place Cloudflare (free tier sufficient) or AWS CloudFront in front of your origin. Ensure the CDN's cache rules allow caching of static assets.
Detection
-
ID:
cdn-caching -
Severity:
info -
What to look for: Count all relevant instances and enumerate each. Check the project's hosting configuration. Look for CDN usage (Vercel Edge Network, Cloudflare, AWS CloudFront, etc.). Verify assets are cached with
cache-controlheaders. Check DNS or deployment config for CDN integration. -
Pass criteria: Static assets (JS, CSS, images) are served from a CDN with geographic edge caching. At least 1 implementation must be verified. Cache-Control headers are set:
immutablewithmax-age=31536000for versioned assets, orno-cachefor dynamic content. -
Fail criteria: Assets served from origin server only (no CDN), or CDN is not configured. Every request travels to origin regardless of geographic location. Cache headers missing or set to short TTL.
-
Skip (N/A) when: The project is deployed to a single region with no geographic distribution needs.
-
Detail on fail: Describe the CDN gap. Example:
"All requests go to origin in us-east-1; users in APAC experience 300ms+ latency. No CDN in front"or"CDN configured but cache headers not set; assets not cached at edges". -
Remediation: Modern platforms include CDN by default:
Vercel: Uses Vercel Edge Network globally by default. Netlify: Uses Netlify Edge globally by default. Cloudflare: Global CDN with 200+ edge locations.
Set cache headers:
// next.config.ts const config = { headers: async () => { return [ { source: '/static/:path*', headers: [ { key: 'cache-control', value: 'public, max-age=31536000, immutable' } ] } ] } }
External references
- iso-25010:2011 · performance-efficiency.time-behaviour — Time Behaviour
Taxons
History
- 2026-04-18·v1.0.0·Initial import from performance-core·automated