Caching Image Derivativesfor Drupal 11 , 10 , 9 , and 8

Last updated :  

You already know derivatives generate lazily on first request, from the Creating Optimized Image Styles lesson — but generation is only half the performance story. Once generated, that derivative file needs to actually stay cached and get served efficiently on every subsequent request, not regenerated or re-fetched unnecessarily. This lesson closes the loop on image performance: making sure the work you've already paid for stays paid for.

What you'll learn in this lesson

  • Where generated derivatives actually live, and why that matters for backups/deploys
  • The HTTP cache headers that keep browsers from re-downloading unchanged derivatives
  • What happens to derivatives when you delete or replace the source image

Where derivatives actually live

# Generated derivatives are real files on disk, not database records:
ls public://styles/article_thumbnail/public/
A deploy/backup gotcha worth knowing: because derivatives are just files under public://styles/, they're regeneratable — deleting the entire directory doesn't lose any real data, Drupal just lazily regenerates each one again on its next request. Some deploy pipelines deliberately clear this directory on deploy to guarantee fresh derivatives after a code change that affects rendering; just be aware that does mean the very next visitor to each image pays the generation cost again.

Browser-side caching via HTTP headers

# nginx — long cache lifetime for generated derivatives specifically,
# since their URL includes the style name and changes if content changes.
location ~ ^/sites/default/files/styles/ {
    expires 1y;
    add_header Cache-Control "public, immutable";
}

A derivative's URL is stable for a given source image + style combination — if the source image changes, Drupal generates a new derivative file (the old one becomes orphaned, not overwritten in place, in most configurations). That stability is exactly what makes a very long, aggressive browser cache lifetime safe here, unlike a page URL that might show different content on every visit.

What happens when you delete or replace a source image

Deleting a source file entity triggers Drupal to flush its associated derivatives via ImageStyleInterface::flush() — but a visitor whose browser already cached the old derivative URL (thanks to the aggressive caching above) may keep seeing it from their own local cache until that expires, since the browser has no way to know the server-side file changed without a URL change of its own.

Quick check: you've set a 1-year browser cache lifetime on image style derivatives (as shown above), and now need to replace a specific image with an updated version at the exact same file path. Will visitors with the old version already cached see the update immediately? If you said no — not until their local cache expires, since nothing about the URL itself signals a change — you've understood the real trade-off of aggressive derivative caching.

Key takeaways

  • Generated derivatives are plain files under public://styles/ — deletable and regeneratable, not permanent data.
  • Derivative URLs are stable per source-image-and-style combination, making a very long browser cache lifetime safe.
  • Deleting a source file flushes its derivatives server-side, but visitors' own browser caches may still serve stale copies until they expire.
  • Some deploy pipelines intentionally clear the styles directory on deploy — know that trade-off before doing it on a high-traffic site.

Coming up next

You've now covered the complete image-optimization toolkit — styles, compression, format, responsive delivery, and derivative caching. Next, we shift to an entirely different performance surface: making search itself fast, starting with Search API query optimization.