I’ve used cloud functions of many flavors over the years, from AWS Lambda to Google Cloud Functions to Val Town. Cloudflare Workers is the latest and greatest, a powerful refinement of the genre, and it’s been the canvas for most of my programming lately.
Here is a report about a recent mini-struggle on the platform, caused by my confusion about how it’s all wired up.
Workers grant you programmatic access to Cloudflare’s caching infrastructure, so it seems like you ought to be able to run a tight little globally-cached web server, merrily spitting out files stored in R2, like so:
export default {
async fetch(request, env, ctx) {
const cache = caches.default;
const cachedResponse = await cache.match(request);
if (cachedResponse) {
return cachedResponse;
}
// Not in the cache, so, proceed to R2
const url = new URL(request.url);
const key = url.pathname.slice(1); // to make R2 key
const object = await env.BUCKET.get(key);
if (object === null) {
// return 404 page
}
const freshResponse = new Response(object.body, {
status: 200,
headers: {
"Content-Type": object.httpMetadata.contentType || "text/html",
"Cache-Control": "public, max-age=604800",
"Festina-Lente": "true"
},
});
// Cache it!!
ctx.waitUntil(cache.put(request, freshResponse.clone()));
return freshResponse;
},
};
Seems like it … but, alas, it’s not that simple, for two reasons:
- The cache available to Workers is per-datacenter, rather than global like Cloudflare’s “traditional” cache. This means that the first request to any given datacenter won’t hit a cache, which is annoying, but not a showstopper.
Here is the showstopper:
- The cache available to Workers can't be controlled by the Cache API. So, to purge files from the Workers cache (after, e.g., uploading fresh versions to R2), you'd have to write your own invalidation layer.
Which maybe sounds fun to some people —
Here I will be precise. There is one way to control the Workers cache using the Cache API. You can simply
{ purge_everything: true }
but that feels pretty gross, right? Again, the attraction was simplicity —
But Robin (you might say, as I said to myself), why don’t you just use a worker as an origin, running its responses through the same “traditional” cache that Cloudflare provides for any other origin, e.g. the old Linux box whirring next to your minifridge? Another disappointment. When you connect a domain to a worker, Cloudflare passes requests straight through, as Chris Krycho discovered.
For anybody else struggling —
P.S. The circuitous complexity of this page in Cloudflare’s docs might illustrate the depth of the confusion here 😵💫
P.P.S. Type the word this many times in a row, and you realize “worker” is weird-looking and weird-sounding! Wrrr-krrr?!
To the blog home page