shiichan

cf.vary Comes to Workers fetch: Fine-Grained Cache Control!

Hey there, it's me, Shiichan! Today I found a quiet-but-nice caching update to share with you.

Cloudflare Changelog developers.cloudflare.com

What was announced?

Over on the Cloudflare Changelog, they announced that Workers fetch() requests now support the cf.vary option. With it, you can control how Cloudflare caches an origin response that carries a Vary header, all on a single-subrequest basis.

The stage is the Workers fetch() call. You just add vary to the cf option when you call it, which is nice and lightweight.

The story so far

When a Vary header is present, responses are cached separately for each value of request headers like Accept or Accept-Language.

That behavior is correct, but if a header has lots of value variations, your cache can end up missing more often. And until now, there wasn't a way to tune this per fetch.

What changes

By passing cf.vary to fetch(), you get to decide how Vary is handled for that subrequest. For each header you can choose to let it pass through or to normalize its values, so you can deliberately shrink the cache-key variations. Fewer variations means it's easier to lift your cache hit rate.

Dive Deep

Here's what it looks like. You set the overall behavior with default, then override per header with headers.

export default {
  async fetch(request) {
    return fetch(request, {
      cf: {
        vary: {
          default: { action: "bypass" },
          headers: {
            accept: {
              action: "normalize",
              media_types: ["text/html", "application/json"],
            },
            "accept-language": {
              action: "normalize",
              languages: ["en", "fr", "de"],
            },
          },
        },
      },
    });
  },
};

Two things to notice: setting default.action to bypass so Vary is passed through by default, while individually normalizing accept down to specific media_types and accept-language to the target languages.

For the full spec, check out the cf.vary property docs.

Wrap-up

  • Workers fetch() now supports the cf.vary option
  • Control how an origin Vary header affects caching, per subrequest
  • Choose bypass or normalize for each header
  • Great for shrinking value variations and tuning cache hit rates

If you've wrestled with Vary in multilingual or content-negotiation setups, or you want to squeeze out more cache efficiency, this one is for you!