Caching Static Assets Fingerprinting
Content-hash filenames, long-cache headers, HTML revalidation, and CDN invalidation without stuck users.
- performance
- caching
- fingerprinting
- cdn
- http-cache
Static asset caching is solved by a boring contract: content hash in the URL + long-lived Cache-Control + HTML that always points at current hashes. Break any leg and you get either endless re-downloads or users stuck on dead JS.
Docs: web.dev HTTP cache, MDN Caching, HTTP caching headers.
The contract
app.9f3c2a.js → Cache-Control: public, max-age=31536000, immutable
index.html → short TTL or no-cache + revalidate
Build tools (Vite, webpack, Next) emit hashes from file content. Changing one byte → new filename → new URL → cache miss by design.
HTML must not be immortal
# HTML
Cache-Control: no-cache
# or
Cache-Control: max-age=60, stale-while-revalidate=300
If index.html is cached for a year while referencing /app.old.js deleted from the CDN, users get a white screen. CDNs need separate rules for / vs /assets/*.
Headers for fingerprinted files
Cache-Control: public, max-age=31536000, immutable
Content-Encoding: br
immutable reduces pointless revalidation on reload while fresh. Pair with compression — gzip/Brotli.
Service workers
Precache exact hashed URLs. On activate, delete old cache names. Never precache bare /app.js. See Cache Storage.
CDN invalidation
With fingerprinting you rarely purge individual JS files — new deploys just add new objects. Purge HTML and API responses when needed. Avoid “purge everything” as a habit; it spikes origin.
Query-string cache busting (?v=3)
Works but is weaker than path hashes (middleware may ignore query; intermediate caches inconsistent). Prefer path fingerprints.
Source maps and privacy
Don’t long-cache private source maps on a public CDN without access control. Hashed .map can still leak source.
Checklist
- Hash JS/CSS/images/fonts in production builds.
- Long-cache only hashed paths.
- Revalidate HTML/shell.
- SW cache versioned by build ID.
- Verify Network panel:
(disk cache)on second load for assets; HTML revalidates.
Interview out-loud
“Fingerprinted filenames let us set year-long immutable caching safely. HTML revalidates so it always references current hashes. Stuck deploys usually mean HTML was cached too long or assets weren’t hashed.”
How this shows up in interviews
Be ready to define the metric or technique in one sentence, name one measurement approach (DevTools panel, web-vitals, or headers), and cite a concrete fix you would try first. Walk through a before/after: what the waterfall or flame chart showed, what you changed, and which percentile moved. Mention a tradeoff (complexity, caching correctness, or third-party business constraints) so the answer doesn’t sound like a blog checklist.
Production guardrails
Ship behind a flag when the change is risky, watch field p75 for the affected template for at least a few days, and keep a rollback path. Pair lab verification (throttled Performance/Network) with RUM so you don’t celebrate a Lighthouse-only win. Document the owner of any ongoing budget or third-party exception.
Related
Further depth
Teams often under-invest in this topic until an incident or CWV regression. Schedule a one-hour drill: reproduce the failure mode in DevTools, list the top three mitigations for your stack, and file tickets with owners. Revisit after the next major feature that touches networking, rendering, auth, or third parties — those are the moments regressions land. Keep primary documentation links in the runbook so on-call is not searching chat history at 2am.
Concrete artifacts to leave behind: a short architecture note, a CI assertion or header snapshot, and a dashboard panel (lab or field) that would have caught the last bug. Teaching the rest of the team the mental model matters as much as the one-line fix.
Further reading
Related guides
- Compression gzip brotliEnable Brotli/gzip for text assets, pick quality levels, and verify Content-Encoding in production.
- HTTP/2 and HTTP/3 for FrontendWhat H2/H3 change for waterfalls, prioritization, and why domain sharding died — frontend-relevant bits only.
- TTFB and Server TimingDiagnose Time to First Byte with Navigation Timing and break down backend phases via Server-Timing.
- Avoiding Layout ThrashingStop forced sync layout loops: batch DOM reads and writes, use rAF, and fix janky measurement code.
- CLS Optimization TacticsFix cumulative layout shift: dimensions, font metrics, reserved slots, and stable late-loading UI.