Skip to content

fix: treat maxAge 0 as "do not cache" - #263

Open
derrickmehaffy wants to merge 1 commit into
mainfrom
fix/max-age-zero-no-cache
Open

derrickmehaffy wants to merge 1 commit into
mainfrom
fix/max-age-zero-no-cache

Conversation

@derrickmehaffy

Copy link
Copy Markdown
Contributor

What changed and why

maxAge: 0 cached a route forever:

  • keyv and cache-manager read a ttl of 0 as "no expiry", and the value was passed straight through;
  • with cacheControl enabled, the same response told clients max-age=0, while the server kept serving it from the cache indefinitely;
  • the docs never defined 0.

Decision (maintainer): maxAge: 0 means do not cache.

Fix:

  • recv.ts: a route whose resolved maxAge is <= 0 returns its response without writing an entry or an ETag. An ETag would be useless anyway, because the server could never revalidate it.
  • cacheStore.set refuses a lifetime <= 0 for any caller, including application code, rather than store it forever.
  • Positive maxAge values are unchanged.
  • Identical concurrent requests are still coalesced into one origin call. Nothing is stored, and they share a key, so it's the same response they'd each get. This is documented.

Behaviour change: only for configurations that set maxAge: 0. They move from cached-forever, which contradicted their own Cache-Control, to not cached, as decided. Documented in docs/guide/caching/index.md.

Tests

New shared/tests/max-age-zero.test.js, using the existing CATEGORY_MAX_AGE fixture switch:

Test On main With the fix
A maxAge: 0 route is a MISS on the second request ✕ (HIT) ✓
Nothing is stored for it ✕ ✓
cacheStore.set(key, val, 0) stores nothing ✕ ✓
A positive-maxAge route still caches (guard) ✓ ✓

The full memory suite passes 252/252, and test:lint is green.

Checklist

  • Tests added. A spec that fails before the change.
  • pnpm run test:e2e:memory passes.
  • pnpm run test:lint passes.
  • Durations: milliseconds, no conversion.
  • User-visible change? docs/guide/ updated.
  • Conventional commit subjects, branched from main.

keyv and cache-manager read a ttl of 0 as "no expiry", so a route configured
with maxAge 0 was stored forever - while, with cacheControl enabled, the
response itself told clients max-age=0.

A maxAge of 0 or less now stores nothing: recv returns the response without
writing an entry or an ETag, and cacheStore.set refuses such a lifetime for
any caller. Positive maxAge values are unchanged.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant