Why Cache Testing Matters

Caching dramatically improves web performance by storing copies of resources so they do not need to be fetched from the server every time. However, incorrect caching leads to users seeing outdated content, receiving stale API responses, or experiencing broken pages after deployments.

The famous quote “There are only two hard things in computer science: cache invalidation and naming things” exists because caching bugs are notoriously difficult to reproduce and debug.

Cache Layers

graph LR User[User Browser] -->|1| BC[Browser Cache] BC -->|2| CDN[CDN Edge Cache] CDN -->|3| RP[Reverse Proxy Cache] RP -->|4| AC[Application Cache] AC -->|5| DB[Database]

Each layer can independently cache and serve stale content.

Browser Cache

Stores resources locally on the user’s device. Controlled by Cache-Control and ETag response headers.

CDN Cache

Stores copies at edge locations worldwide. Reduces latency by serving content from the nearest server.

Server-Side Cache

Application-level caching (Redis, Memcached) that stores computed results, database queries, or API responses.

Key Cache Headers

HeaderPurposeExample
Cache-ControlPrimary caching directivemax-age=3600, public
ETagContent fingerprint for validation"abc123def456"
Last-ModifiedWhen content was last changedTue, 19 Mar 2026 10:00:00 GMT
ExpiresAbsolute expiration date (legacy)Tue, 19 Mar 2026 11:00:00 GMT
VaryCache varies by request headerVary: Accept-Encoding, Accept-Language

Cache-Control Directives

DirectiveMeaning
publicCan be cached by any cache (browser, CDN, proxy)
privateCan only be cached by the user’s browser
no-cacheMust revalidate with server before using cached copy
no-storeMust not be cached at all
max-age=NCache is valid for N seconds
s-maxage=NCDN/proxy cache duration (overrides max-age for shared caches)
immutableContent will never change — browser can skip revalidation

What to Test

Correct Caching Behavior

Resource TypeExpected CachingWhy
Static assets (JS, CSS, images)Long cache (1 year) with hash in filenameContent-addressable, cache busting handles updates
HTML pagesShort cache or no-cacheContent changes frequently
API responses (public data)Short cache (minutes)Balance freshness and performance
API responses (user-specific)private, no-cache or no-storePrevent data leakage between users
Authentication endpointsno-storeSensitive data must never be cached

Cache Invalidation After Deployment

  1. Deploy a change to CSS/JS
  2. Verify that users get the new version (check file hash in URL changed)
  3. Verify old cached version does not break the new HTML
  4. Test with the browser cache populated from before the deployment

Stale Content Scenarios

  • Update a product price — does the old price persist in any cache?
  • Change a user’s role — do cached permission checks still show old role?
  • Delete content — does the cached version still serve the deleted page?
  • Update a profile image — does the old image persist?

Cache and Authentication

  • User A’s data must never be served from cache to User B
  • Logging out must invalidate cached user-specific content
  • Vary: Cookie or private must be used for authenticated responses
  • CDN must not cache authenticated API responses

Exercise: Cache Testing Audit

Perform a caching audit on a web application.

Step 1: Inspect Cache Headers

Open DevTools > Network tab. Load the page and check headers for different resource types:

ResourceCache-ControlETagMax-AgeCorrect?
HTML page
CSS file
JavaScript bundle
Image
API response (public)
API response (authenticated)

Step 2: Test Cache Busting

  1. Note the current JS/CSS file URLs (with hashes)
  2. Make a code change and deploy
  3. Verify file URLs have changed (new hashes)
  4. Hard refresh (Ctrl+Shift+R) should load new files
  5. Normal refresh should also load new files (if HTML is not cached)

Step 3: Test Stale Content

  1. Load a page with dynamic content (user profile, product)
  2. Update the content via another browser/API
  3. Refresh in the original browser
  4. Verify updated content is displayed (not stale cache)

Step 4: Cross-User Cache Test

  1. Log in as User A, visit profile page
  2. Note the API response in DevTools (User A’s data)
  3. Log out and log in as User B
  4. Visit the same profile endpoint
  5. Verify you see User B’s data (not User A’s cached data)
Solution: Common Caching Bugs

Bug 1: CSS cached without hash in URL After deployment, users saw the old CSS because the file URL did not change. Fix: Implement cache busting with content hashes (e.g., style.abc123.css).

Bug 2: Authenticated API response cached by CDN CDN cached a user’s profile API response and served it to other users. Fix: Add Cache-Control: private, no-store to all authenticated endpoints.

Bug 3: Product price cached for 1 hour After updating a sale price, customers saw the old price for up to 1 hour. Fix: Reduce cache TTL for price-sensitive content or implement cache purge on price updates.

Bug 4: Stale HTML after deployment HTML page was cached with 1-hour max-age. After deploying new JS bundles, the old HTML referenced old JS file URLs that no longer existed. Fix: Use no-cache for HTML so browsers always revalidate.

Bug 5: Browser back button shows cached sensitive data After logging out, pressing the back button showed the previous user’s dashboard from browser cache. Fix: Add Cache-Control: no-store to all authenticated pages.

Debugging Cache Issues

Chrome DevTools

  1. Disable cache checkbox in Network tab (for testing without cache)
  2. Hard refresh (Ctrl+Shift+R) bypasses browser cache
  3. Check Size column: “disk cache” or “memory cache” = served from cache
  4. Check response headers for Cache-Control, ETag, Age
  5. Application > Cache Storage shows Service Worker caches

curl for Header Inspection

# Check cache headers
curl -I https://example.com/page

# Check if CDN is serving cached content (look for Age header)
curl -I https://example.com/style.css | grep -i "age\|cache-control\|etag"

Key Takeaways

  • Cache testing must cover all layers: browser, CDN, and server-side
  • Static assets should use long cache with content hashes for cache busting
  • HTML should use no-cache to ensure users always get the latest version
  • Authenticated responses must use private or no-store to prevent cross-user data leakage
  • Always test cache behavior after deployments to verify users get updated content
  • The browser back button can serve stale cached content — test logout flows carefully