Asset File Caching

Asset files such as multimedia files, javascript, and CSS typically are cached by the edge network according to the caching profiles.

Modern web framework asset handling often renames files with distinct fingerprints or means of assisting with asset caching. If those aren't available in your framework, you'll need to manually clear the cache after deploying your application.

Asset file extensions

Files served by your Heroku application that end in any of the following file extensions are considered assets and are cached for 3 days:
js, css, png, swf, jpg, jpeg, svg, svz, gif, ico, mp3, mp4, odf, pdf, woff, woff2, ttf, thumb, webp, txt, otf, 7z, aac, ai, asf, avi, bmp, bz2, doc, docx, eot, eps, fla, flv, gz, ind, m4a, m4v, mkv, mko, mpeg, oga, ogx, pptx, psd, rar, rtf, tar, tgz, tiff, wav, xlsx, xml, zip, zipx

Browser cache headers on asset URLs

In addition to being cached at the edge, responses served at asset URLs are sent to visitors with far-future Cache-Control and Expires headers so that browsers cache them locally. These headers are set by the edge network based on the URL’s file extension:

  • They are applied in every caching profile, including Assets Only.
  • They replace any Cache-Control header your application sets on that URL.
  • They are applied to any response served at an asset URL, including redirects, not just the files themselves.
  • Adding the URL as a Non-Cached Path stops edge caching but does not change these headers.

This works well for fingerprinted assets, where the URL changes whenever the content changes. It causes problems for URLs that end in an asset extension but return short-lived responses. The most common case is a framework route that redirects an image URL to a temporary signed storage URL (for example, Rails Active Storage in its default redirect mode). The browser caches the redirect long after the signed URL has expired, and the image breaks.

For those routes, configure your application to serve the file directly instead of redirecting. See the Rails Active Storage article for the recommended configuration, or contact support to have header handling adjusted for your site.

Versioning cache URLs

How URL query parameters interact with the cache depends on whether the URL is an asset URL (one that ends in an extension from the list above) or a page.

For pages, each distinct query string is cached as a distinct resource. This means that:

https://example.com/users/?id=1

and

https://example.com/users/?id=2

are cached separately, and requesting the second does not return the cached results for the first.

For asset URLs, adding a query string prevents edge caching entirely. A request like app.css?v=2 is passed through to your application every time. Query-based versioning does work as a cache buster, but the asset loses the benefit of the CDN cache. To version assets, change the URL path instead: use a fingerprinted filename from your framework asset pipeline, or a name like app.v2.css.