Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions vercel.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
{
"key": "Link",
"value": "</llms.txt>; rel=\"describedby\"; type=\"text/plain\", </api-reference/introduction>; rel=\"service-doc\"; type=\"text/html\", </sitemap.xml>; rel=\"sitemap\"; type=\"application/xml\""
},
{
"key": "Vary",
"value": "accept"
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider using the canonical header name casing in the Vary value (i.e., Accept instead of accept) for consistency with HTTP specs and the external references mentioned in the PR description, and to reduce the chance of any intermediary treating the token case-sensitively.

Suggested change
"value": "accept"
"value": "Accept"

Copilot uses AI. Check for mistakes.
}
Comment on lines +11 to 14
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🌐 Web query:

How does Vercel's edge CDN handle Vary: Accept — does it normalize the Accept header into buckets or key the cache on the raw value?

💡 Result:

Vercel's Edge CDN keys the cache on the raw value of the Accept header rather than normalizing it into buckets. The Accept header is included in the cache key by default, even without an explicit Vary: Accept response header. When a Vary: Accept header is set (along with a caching Cache-Control like s-maxage), the CDN creates unique cache entries for each distinct combination of the base cache key and the raw Accept header value from the request. This standard HTTP Vary behavior ensures correct content negotiation (e.g., serving WebP vs JPEG based on browser Accept headers) but can lead to high cache fragmentation if Accept values vary widely across clients, as no normalization or bucketing is mentioned or implied in official docs.

Citations:


Change "accept" to "Accept" to match HTTP header naming conventions (line 13).

This is functionally correct and solves the stale-HTML-for-agents problem. However, Vary: Accept creates unique cache entries for each raw Accept header value on Vercel's CDN (no normalization is performed). Since browsers send highly variable Accept headers (e.g. text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 with differences across Chrome/Firefox/Safari/versions), this significantly fragments the cache by keying on the full raw header string.

Monitor hit-rate impact after rollout. If cache efficiency regresses, consider a more targeted approach using custom middleware headers that only distinguish markdown vs. html, then Vary on that instead—this gives the same content negotiation without the cardinality cost.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@vercel.json` around lines 11 - 14, Replace the Vary header value "accept"
with "Accept" to match HTTP header casing (change the value for the object with
"key": "Vary"), then deploy and monitor CDN cache hit-rate; if cache
fragmentation increases, implement a more targeted negotiation: add a custom
middleware header (e.g., "X-Preferred-Format" or similar) that maps incoming
Accept strings to a small set like "markdown" or "html", set that header on
responses and change Vary to that custom header instead to avoid high
cardinality.

]
}
Expand Down
Loading