Cache-Control no-store + max-age Conflict: How to Fix Caching Chaos

Diagnose and resolve contradictory cache directives that cause random hit/miss behavior.

When `no-store` appears together with `max-age` or `immutable`, caches and teams read the policy differently. This guide gives a deterministic fix path.

Tools in this guide

Symptoms

  • Responses randomly switch between cache hit and origin fetch.
  • CDN behavior differs from browser cache behavior for the same URL.
  • Auth-related responses occasionally leak stale or wrong user state.

Root Cause

  • `no-store` is combined with `max-age` / `immutable`, creating contradictory directives.
  • `private` and shared cache expectations are mixed without explicit policy separation.
  • Validator strategy (`ETag` / `Last-Modified`) is missing, forcing hard fallback after TTL.

Fix Steps

  1. Parse raw Cache-Control value and remove contradictory directives first.
  2. Split policy by response type: auth/session routes use strict no-store/private, static/API cacheable routes use explicit TTL.
  3. If stale serving is desired, add `stale-while-revalidate` and validator headers to control revalidation behavior.

Safe baseline for sensitive API responses

Cache-Control: private, no-store
Pragma: no-cache

FAQ

Can no-store and max-age exist together?

Technically possible, but operationally contradictory and should be avoided.

When should I use stale-while-revalidate?

Use it for non-sensitive cacheable content where brief staleness is acceptable.