-
-
Notifications
You must be signed in to change notification settings - Fork 806
Netlify preset: defineCachedEventHandler doesn't emit Netlify-Vary: query, causing query-variant cache collapse #4165
Description
Environment
nitro v2, using netlify-edge preset.
The issue should also happen with netlify functions.
Reproduction
I spotted the bug using @nuxt/icon but the issue is broader.
@nuxt/icon registers /api/_nuxt_icon/[collection].json using:
defineCachedEventHandler(handler, {
getKey(event) {
const icons = String(getQuery(event).icons || "");
return `${collection}_${icons.split(",")[0]}_${icons.length}_${hash(icons)}`;
},
swr: true,
maxAge: 60 * 60 * 24 * 7,
}); The handler returns different JSON depending on the ?icons= query param. Nitro emits:
cache-control: s-maxage=604800, stale-while-revalidate
Netlify CDN caches this. The next request to the same path with a different ?icons= value gets the cached response from the first request — wrong icons.
Describe the bug
When using the Netlify preset, defineCachedEventHandler with a query-based getKey emits cache-control: s-maxage=..., stale-while-revalidate — which Netlify CDN honours by caching the response. But because no Netlify-Vary: query header is present, the CDN collapses all query string variants into a single cache entry, serving the first-cached response for every subsequent variant.
Nitro's server-side cache works correctly (it keys by the query-derived value). The CDN layer silently breaks it.
I managed to work around the issue by adding the netlify-vary header manually in Nuxt's routeRules:
// nuxt.config.ts
routeRules: {
'/api/_nuxt_icon/*': {
headers: { 'Netlify-Vary': 'query' },
},
}
Additional context
No response