Docs/Sites/Site Cache-Control

Site Cache-Control

The Cache-Control header openkbs site deploy stamps on each file type, and how to override it per path with cacheControl rules in openkbs.json.

2 min readUpdated

This page describes what openkbs site deploy stamps on each file. The defaults are safe for every site — add cacheControl only when you need something different.

Defaults

FileDefault
.html and extensionless routesno-cache, no-store, must-revalidate
service workers (*sw.js, service-worker.js, workbox-*.js, ngsw-worker.js, ngsw.json)no-cache, max-age=0, must-revalidate
content-hashed js/css/fonts (index-DkT3vQwZ.js, main.8f7e6d5c.css) and everything under _next/static/, _app/immutable/public, max-age=31536000, immutable
unhashed .js .mjs .css .map .txt .xml .json .webmanifest .csv (app.js, robots.txt, sitemap.xml, manifest.json)public, max-age=3600
everything else: images, fonts, video, PDF, wasm with fixed namespublic, max-age=86400

No other folder is special — assets/logo.png is a plain image (1 day), and Inter-SemiBold.woff2 / styles-v10.css are not hashes. Only a hex or random 8-char chunk right before the extension makes a file immutable; a hashed .png/.wasm needs a rule below.

Per-path overrides

Override per path — pattern → header value, last matching pattern wins, so keep generic patterns above specific ones:

json
{
  "site": "./site",
  "cacheControl": {
    "/images/**": "public, max-age=604800",
    "/images/logo.png": "no-cache",
    "/**/*.wasm": "public, max-age=31536000, immutable"
  }
}

Patterns start with / and match the file path under site/ (/pricing.html, even with cleanUrls; /pricing matches nothing). * matches within one path segment; ** is a whole segment matching any depth (/images/**, /**/*.js; not /images/**/ or /**.js). Max 50 rules. Values are plain Cache-Control strings (letters, digits, space, comma, =, -). HTML is not exempt — a rule can cache pages too, which delays every content update for that long. The deploy prints how many files matched; 0 means the patterns are wrong.

When rules take effect

Rules apply on the next deploy (every file is re-uploaded). Browsers that already hold a file under immutable keep it until their cache evicts it — the only way to reach them is a new filename. openkbs site invalidate purges the CDN edge, never browsers.

A Netlify/Cloudflare-style _headers file is not interpreted — it uploads as a plain file. Cache-Control is the only per-file header that can be set; security headers are site-wide via securityHeaders.

Building something for your company?
We co-build production systems with enterprise teams on this platform.