# 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:

```ts
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.

<tip>

**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.

</tip>

## 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`.

<note>

**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.

```ts
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
});
```

</note>
