Dynamic AVIF Serving and Cache-Control Headers
Dynamically serving AVIF images based on incoming client headers
dramatically reduces payload sizes, but it introduces critical caching
challenges across intermediate proxies, Content Delivery Networks
(CDNs), and browser caches. Because the same asset URL can yield
multiple binary formats (such as AVIF, WebP, or JPEG) depending on
client support, misconfigured caching rules can cause incompatible
formats to be cached and served to unsupported browsers. Correctly
orchestrating the Cache-Control and Vary HTTP
headers is essential to ensure high cache hit ratios, prevent cache
poisoning, and minimize server compute load.
The Critical Role of
Vary: Accept
When serving AVIF dynamically, the origin server inspects the
client’s Accept request header to determine whether the
browser supports image/avif. Because the response body
changes depending on this header, the origin must include:
Vary: Accept
The Vary: Accept header instructs downstream caches
(both local browser caches and shared CDNs) to store distinct cached
representations of the resource indexed by the client's
Accept header. Omitting Vary: Accept leads to
cache pollution: if an AVIF-capable browser requests
/image.jpg first, a cache without Vary will
store the AVIF payload under that URL. Subsequent requests from an older
browser will then receive the cached AVIF file, leading to a broken
image display.
Cache-Control
Directives for Dynamically Transcoded Media
AVIF encoding requires substantial CPU resources compared to legacy formats. Caching these responses aggressively is mandatory to prevent performance degradation at the origin.
public: Explicitly permits intermediate proxies and CDNs to store the response, which is required for shared caching.max-ageands-maxage: Use a long duration (e.g.,max-age=31536000) for immutable or static media. Uses-maxageto control edge cache retention independently from browser retention.stale-while-revalidate: This directive allows the CDN to serve a stale cached version of the image immediately while fetching or transcoding an updated version in the background, smoothing latency spikes during cache churn.
An optimal production header configuration often looks like:
Cache-Control: public, max-age=86400, s-maxage=31536000, stale-while-revalidate=604800
Vary: Accept
CDN Cache Key Fragmentation and Normalization
While Vary: Accept guarantees correctness, it creates a
performance issue known as cache key fragmentation. Browsers send
diverse, lengthy Accept headers. For instance, Chrome,
Firefox, and Safari each send slightly different MIME type lists in
their Accept strings.
If a CDN adheres strictly to the raw Accept string, it
will create separate cache entries for identical AVIF files, lowering
the CDN cache hit ratio and triggering unnecessary dynamic encoding on
the origin.
To resolve this, edge servers or CDNs must normalize the
Accept header before evaluating the cache key. The CDN edge
worker or cache rule should parse the Accept header and
classify it into discrete buckets:
- Supports AVIF (
image/avif) - Supports WebP (
image/webp) - Fallback (standard JPEG/PNG)
By modifying the cache key to depend on the normalized format bucket
rather than the raw Accept header string, you maintain
correctness without fragmenting the cache.
Entity Tags (ETags) and Conditional Requests
When serving multiple representations from a single URL, weak validation becomes necessary if the representations share semantic meaning but have different byte streams.
If you use strong ETags (e.g., ETag: "12345"), a
validator generated for an AVIF payload will clash if an intermediate
cache checks it against a fallback JPEG representation. When using
dynamic format negotiation, apply representation-specific ETags (e.g.,
ETag: W/"12345-avif") to prevent erroneous
304 Not Modified responses across different image
formats.
Header-Based Negotiation vs. File Extension Rewriting
Header-based dynamic negotiation maintains a clean URL structure
(e.g., <img src="photo.jpg"> serving AVIF
transparently). However, because of the reliance on complex
Vary semantics and CDN edge logic, many high-scale
architectures choose to decouple format selection from HTTP headers
entirely.
By handling format detection at the application layer or edge
(rewriting the markup to output <picture> elements
pointing to distinct static URLs like photo.avif and
photo.webp), caching simplifies considerably. Static URLs
allow standard, straightforward Cache-Control headers
without the overhead of Vary: Accept parsing and edge cache
normalization.