Static routes send no Cache-Control or ETag — returning visitors get stale pages, and mixed stale HTML/CSS breaks the render Issue open
Migrated from github.com/carlosframework/platform issue #234, opened 2026-08-19. GitHub issues are closed for this repo; see AGENTS.md, "Work is tracked on amadan, not GitHub".
Still outstanding: Static routes send no Cache-Control or ETag, so returning visitors get stale pages and mixed asset versions.
---
What
Static routes serve only Last-Modified. No Cache-Control, no ETag.
$ curl -sI https://carlosframework.com/
last-modified: Wed, 19 Aug 2026 13:20:59 GMT
x-carlos-version: 89a5864
$ curl -sI https://carlosframework.com/site.css
last-modified: Wed, 19 Aug 2026 13:20:59 GMT
x-carlos-version: 89a5864With no Cache-Control, browsers apply heuristic caching — commonly ~10% of the elapsed time since Last-Modified. For a page that had not changed in weeks, that is days of staleness for a returning visitor.
Why it matters more than "stale content"
Assets expire independently. Observed on carlosframework.com within minutes of the redesign deploy (afe6833 → 89a5864), in a real browser:
- One view served the entire old page — old markup, old stylesheet. Looked like the deploy never happened.
- Another served the new HTML against the old cached
site.css. That is the damaging one: the page rendered with the retired serif, and the new inline-SVG wordmark — which the new stylesheet sizes and strokes — rendered as a row of giant black shapes across the top of the page.
So the failure mode is not "a visitor sees yesterday's copy". It is "a visitor sees a broken page", and neither the operator nor X-Carlos-Version shows it, because the server is serving the right bytes.
This also silently undercuts the "convergence is seconds" story: a promote reaches the edge in ~2s and then waits days in the visitor's browser.
Suggested shape
Content-addressed releases make this easy to get right:
- HTML (and anything without a fingerprint):
Cache-Control: no-cache— revalidate every time. Cheap, because anETag/If-None-Matchpair makes the common case a 304. - Fingerprinted assets, if/when static ships them:
Cache-Control: public, max-age=31536000, immutable. - Emit a strong
ETagfor every static object. The release is content-addressed already, so the digest is in hand — this is close to free.
A sensible default of no-cache + ETag for all static objects would fix the reported breakage on its own, and a per-app or per-route override could come later if anyone needs long max-age.
Workaround in place meanwhile
carlosframework/website now (a) gives every inline SVG width/height/fill/stroke as presentation attributes so a stale stylesheet degrades to a sane outline rather than a black blob, and (b) links the stylesheet as site.css?v=<sha>, bumped at deploy. Both are documented in that repo's CLAUDE.md as workarounds for this issue. Neither helps a visitor whose HTML is stale — only the server can fix that case.