DEV Community

Weather Clock Dash
Weather Clock Dash

Posted on

Firefox Cache: HTTP Caching, BFCache, Service Worker Cache, and How to Debug Stale Files

Browser caching affects web development workflows in ways that aren't always obvious. Understanding Firefox's caching layers, how to control them, and when to disable them saves debugging time.

Firefox's Caching Layers

Firefox uses multiple caches:

  1. Memory cache: Short-lived, stores recently loaded resources in RAM
  2. Disk cache: Persistent cache on disk, stores resources across sessions
  3. Service worker cache: Managed by service workers (Cache API)
  4. HTTP cache: Governed by server-sent headers (Cache-Control, Expires, ETag)
  5. Back/Forward cache (BFCache): Caches entire page state for back/forward navigation

Network Panel Cache Controls

In DevTools → Network panel:

  • Disable Cache checkbox: Disables the memory and disk cache for as long as DevTools is open. Resources are re-fetched every request.

When to enable: During development, when testing changes to CSS/JS/images. Prevents stale files from appearing.

Note: "Disable Cache" in DevTools only works while DevTools is open. Close DevTools and caching resumes.

Hard Reload vs Soft Reload

  • F5 or Ctrl+R: Reload — uses cache (may serve cached files)
  • Ctrl+Shift+R or Ctrl+F5: Hard Reload — ignores cache, fetches everything fresh
  • Shift+Click reload button: Also triggers hard reload

What hard reload does: Sends Cache-Control: no-cache header with every request. Server should respond with fresh content (but ETag validation may still occur).

Hard reload does NOT clear the cache — it bypasses it for this request but the cached copy remains.

Clearing the Cache

Clear just cache (not cookies):

  1. Settings → Privacy & Security → Cookies and Site Data → Clear Data
  2. Uncheck "Cookies and Site Data", leave "Cached Web Content" checked
  3. Clear Data

From keyboard: Ctrl+Shift+Delete → choose "Cache" only → clear.

Clear for specific site:

  1. Click lock icon in address bar → Connection Secure → More Information
  2. → Security tab → View Certificates OR:
  3. Settings → Privacy → Cookies and Site Data → Manage Data → search site → remove

Or: DevTools → Storage → Cache Storage → right-click the cache → Delete All.

Cache Inspector (about:cache)

about:cache shows what's currently in Firefox's cache:

  • Memory cache: files in RAM
  • Disk cache: files on disk
  • Click "List Cache Entries" for each type to see all cached URLs

For debugging a specific URL: Search in the cache entry list for your URL. Click to see:

  • Request headers cached
  • Response headers
  • Last fetched time
  • Expiry time

This is how you verify a resource IS in cache and hasn't expired.

HTTP Cache Headers Explained

How Firefox decides to use cache:

  1. Check Expires header — if expired, fetch fresh
  2. Check Cache-Control: max-age=N — if older than N seconds, fetch fresh
  3. If cached but may be stale: send conditional request with If-None-Match (ETag) or If-Modified-Since
  4. If server returns 304 Not Modified: use cached copy
  5. If server returns 200: update cache with new response

Key headers:

Cache-Control: no-store       → Never cache
Cache-Control: no-cache       → Always revalidate before use
Cache-Control: max-age=3600   → Cache for 1 hour
Cache-Control: immutable      → Cache forever (content won't change)
ETag: "abc123"                → Version identifier for revalidation
Vary: Accept-Encoding         → Cache separately per content-encoding
Enter fullscreen mode Exit fullscreen mode

For development servers: Set Cache-Control: no-store on HTML responses and Cache-Control: max-age=0 on assets you frequently update. This forces full fetches during development.

For production:

  • Immutable static assets: Cache-Control: public, max-age=31536000, immutable (with hashed filenames)
  • HTML: Cache-Control: no-cache (revalidate on each visit)
  • API responses: Cache-Control: no-store or appropriate TTL

Service Worker Cache

Service workers have their own cache (separate from the HTTP cache):

// Check what's in service worker cache
const caches_list = await caches.keys();
for (const name of caches_list) {
  const cache = await caches.open(name);
  const keys = await cache.keys();
  console.log(`${name}: ${keys.length} entries`);
  keys.forEach(r => console.log(' -', r.url));
}
Enter fullscreen mode Exit fullscreen mode

Service worker cache is persistent — it doesn't respect "hard reload" unless the service worker explicitly handles that.

Clear service worker cache:

  1. DevTools → Storage → Cache Storage → right-click → delete
  2. Or: about:serviceworkers → find your site → unregister service worker

The catch: Even after unregistering the service worker, the next page load will re-register it. To debug without any service worker: add ?nosw or similar and handle it in your service worker code.

Back/Forward Cache (BFCache)

Firefox's BFCache stores entire page states for instant back/forward navigation.

What's stored: The full page in memory — JS heap, scroll position, form values, everything.

When pages are NOT cached in BFCache:

  • Pages with Cache-Control: no-store
  • Pages with unload event handlers (deprecated behavior)
  • Pages with open IndexedDB transactions
  • Pages with active WebRTC connections
  • Pages with service workers in some states

Testing BFCache in DevTools: Go to a page → navigate away → press Back → if it restored instantly (no network request), BFCache worked.

Debug BFCache: In about:config: docshell.shistory.bfcache.enable controls BFCache. DevTools now shows BFCache status in the Network panel for back/forward navigations.

Optimizing Cache for Development

Webpack/Vite dev server: Most modern bundlers have built-in cache-busting for development. They serve files with hash-based filenames or ETag-based revalidation.

If you still see stale files: Check in Network panel whether the request was served from "Service Worker", "Memory Cache", "Disk Cache", or "(from fetch)". This tells you which layer is serving the stale file.

Node.js/Express dev server — prevent caching:

app.use((req, res, next) => {
  res.setHeader('Cache-Control', 'no-store, no-cache, must-revalidate');
  res.setHeader('Pragma', 'no-cache');
  res.setHeader('Expires', '0');
  next();
});
Enter fullscreen mode Exit fullscreen mode

Cache Size Management

Firefox's disk cache has a maximum size (configurable in about:config):

browser.cache.disk.capacity = 1048576  (in KB, default ~1GB)
browser.cache.disk.max_entry_size = 51200  (max single entry in KB)
Enter fullscreen mode Exit fullscreen mode

Firefox also respects the clear-site-data HTTP response header:

Clear-Site-Data: "cache", "cookies", "storage"
Enter fullscreen mode Exit fullscreen mode

Sending this header clears all cached data for your origin — useful for logout endpoints or deployment scripts.

Quick Debug Checklist

When you suspect caching issues:

  1. Network panel: Is the response coming from cache or network? Status column shows "304", "(memory cache)", "(disk cache)", or "(service worker)".

  2. Hard reload: Does Ctrl+Shift+R fix the issue? If yes, HTTP cache was the problem.

  3. DevTools cache disabled: Does checking "Disable Cache" fix it? If yes, HTTP cache.

  4. Service worker: Is there a service worker? DevTools → Service Workers. If there is one, it may be serving stale responses. Unregister it to test.

  5. about:cache: Is the stale URL in the cache? What's its expiry?

Most cache bugs fall into two categories: (1) the HTTP cache serving stale assets because of wrong Cache-Control headers, or (2) a service worker serving from its cache without checking for updates.

Top comments (0)