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.

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:

  1. Supports AVIF (image/avif)
  2. Supports WebP (image/webp)
  3. 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.