Cookies

By default, no cookies take part in caching — in either direction. This is a secure default:

  • The Cookie request header is stripped before your handler runs, so the handler can't produce cookie-specific output that then gets cached and served to someone else.
  • Cookies never vary the cache key.
  • Any Set-Cookie your handler sets is removed before the response is cached or returned.

Together these keep a per-request cookie (such as a session id) from ever reaching another visitor — whether through a later cache hit or a concurrent request that is served the same cached response.

const page = defineCachedHandler(
  async (event) => {
    event.req.headers.get("cookie"); // always null for cached GET/HEAD requests
    return new Response(await renderPage(), {
      headers: { "content-type": "text/html" },
    });
  },
  { maxAge: 60 },
);
This only applies to cacheable requests (GET / HEAD). Methods that bypass the cache entirely (POST, PUT, …) reach the handler with the request untouched — cookies, headers, query, and body included — and their Set-Cookie is passed straight through.

Allowing specific cookies

Set allowCookies to an allowlist of cookie names to opt specific cookies back in. For those cookies only:

  • they stay in the Cookie header your handler sees,
  • they vary the cache key (sorted and order-independent, like allowQuery, so only that subset is part of the key — not the entire raw Cookie header),
  • a matching Set-Cookie is allowed to be cached and returned.

Every other cookie is still stripped in both directions, and the rest of the response is cached as usual.

const page = defineCachedHandler(myHandler, {
  maxAge: 300,
  allowCookies: ["theme"], // theme=dark and theme=light cache separately; every other cookie is ignored
});

Cookie names are case-sensitive. allowCookies supersedes varies: ["cookie"] — set the allowlist and drop the coarse varies entry.

Caveats

  • Custom getKey. As with allowQuery, a custom getKey controls the cache key entirely, so allowlisted cookies no longer vary it automatically. If your handler's output depends on a cookie, incorporate it into getKey yourself. (The handler-visible Cookie header is still filtered to the allowlist regardless.)
  • Allowlisted cookies are shared — keep them cache-safe. An allowlisted cookie is part of the cache: its value varies the key, and its Set-Cookie is cached and replayed to every visitor that resolves to the same key (concurrent requests are served a single shared response). Only allowlist cookies whose value is safe to share across everyone who shares that key — a theme or locale preference that is genuinely part of the key.
Never allowlist a per-user secret such as a session id. Because a response is shared across everyone with the same cache key, that one value would leak between users. A handler that mints a per-request cookie (e.g. starting an anonymous session with a fresh Set-Cookie) must give each user a distinct entry via a user-specific getKey / varies — otherwise don't cache it. With no allowCookies, such a cookie is simply stripped, so the default never leaks; this only matters once you opt a cookie back in.