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:
- Memory cache: Short-lived, stores recently loaded resources in RAM
- Disk cache: Persistent cache on disk, stores resources across sessions
-
Service worker cache: Managed by service workers (
CacheAPI) - HTTP cache: Governed by server-sent headers (Cache-Control, Expires, ETag)
- 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):
- Settings → Privacy & Security → Cookies and Site Data → Clear Data
- Uncheck "Cookies and Site Data", leave "Cached Web Content" checked
- Clear Data
From keyboard: Ctrl+Shift+Delete → choose "Cache" only → clear.
Clear for specific site:
- Click lock icon in address bar → Connection Secure → More Information
- → Security tab → View Certificates OR:
- 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:
- Check
Expiresheader — if expired, fetch fresh - Check
Cache-Control: max-age=N— if older than N seconds, fetch fresh - If cached but may be stale: send conditional request with
If-None-Match(ETag) orIf-Modified-Since - If server returns 304 Not Modified: use cached copy
- 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
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-storeor 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));
}
Service worker cache is persistent — it doesn't respect "hard reload" unless the service worker explicitly handles that.
Clear service worker cache:
- DevTools → Storage → Cache Storage → right-click → delete
- 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
unloadevent 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();
});
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)
Firefox also respects the clear-site-data HTTP response header:
Clear-Site-Data: "cache", "cookies", "storage"
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:
Network panel: Is the response coming from cache or network? Status column shows "304", "(memory cache)", "(disk cache)", or "(service worker)".
Hard reload: Does Ctrl+Shift+R fix the issue? If yes, HTTP cache was the problem.
DevTools cache disabled: Does checking "Disable Cache" fix it? If yes, HTTP cache.
Service worker: Is there a service worker? DevTools → Service Workers. If there is one, it may be serving stale responses. Unregister it to test.
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)