Query Parameters

By default the full query string is part of the cache key, so ?color=red and ?color=red&utm=x are cached as separate entries. That means unrelated params — tracking tags, cache-busters — fragment your cache and lower the hit rate.

Set allowQuery to an allowlist of param names so only those vary the key; every other param is ignored:

const handler = defineCachedHandler(
  async (event) => {
    const url = event.url ?? new URL(event.req.url);
    const color = url.searchParams.get("color") ?? "default";
    return new Response(renderSwatch(color), {
      headers: { "content-type": "text/html" },
    });
  },
  {
    maxAge: 300,
    allowQuery: ["color"],
  },
);

// All of these share ONE cached entry (only `color` matters):
await handler({ req: new Request("https://shop.dev/swatch?color=red") });
await handler({ req: new Request("https://shop.dev/swatch?color=red&lang=en") });
await handler({ req: new Request("https://shop.dev/swatch?color=red&utm=ig") });

Matching is order-independent and normalized: ?color=red&size=l and ?size=l&color=red hit the same entry, and repeated (array) params like ?color=red&color=blue are matched regardless of order.

Ignored params never reach the handler. Just like non-varies headers, params outside the allowlist are stripped from the URL the handler receives — so a handler can never accidentally produce output that depends on a param outside the cache key.

Edge cases

  • Cache everything under one key. An empty allowlist (allowQuery: []) drops the whole query string, so every request to the path shares a single entry (and the handler always sees a query-less URL).
  • Case-sensitive. allowQuery: ["color"] does not match ?Color=red.
getKey overrides the key entirely. If you provide a custom getKey, it — not allowQuery — decides the cache key. allowQuery no longer influences the key, but non-allowlisted params are still stripped from the URL the handler sees.
defineCachedHandler(myHandler, {
  maxAge: 300,
  allowQuery: ["color"], // still strips other params from the handler's URL
  getKey: (event) => new URL(event.req.url).pathname, // but this defines the key
});