The Vercel caching bug that silently broke my APIs (and how to fix it)
Hey there,
I just mass spent hours debugging one of the most frustrating issues I've encountered in a while, and I wanted to share it because I'm sure others will hit the same wall.
The Setup
I was building JSON-RPC endpoints for my blog's A2A (Agent-to-Agent) protocol - APIs that let AI agents query blog content. Everything worked perfectly in local development.
The Problem
In production on Vercel, different POST requests started returning the same response:
- Request with
{"type": "site"}→ Returns site metadata ✓ - Request with
{"type": "stats"}→ Returns site metadata ✗ (should be stats!)
Same URL, different POST body, identical cached response.
What Didn't Work
I tried everything that should prevent caching:
Cache-Control: no-store, no-cacheheadersx-vercel-no-cache: 1header- Query parameter cache busting
- CDN-specific headers
- vercel.json configuration
None of it worked. ISR ignored all of it.
The Root Cause
Vercel's ISR caches POST requests by URL path only. It completely ignores: - The POST body content - Query string parameters - All cache-control headers
For JSON-RPC, GraphQL, or any API where the request body determines the response, this silently breaks everything.
The Fix
Explicitly exclude your API routes from ISR:
// astro.config.mjs
adapter: vercel({
isr: {
exclude: ['/api/your-endpoint', '/api/another-endpoint'],
},
})
That's it. Once deployed, each request is processed independently.
Full Details
I wrote up the complete debugging journey with all the code examples, what to look for in response headers, and solutions for both Astro and Next.js:
→ https://colinmcnamara.com/blog/vercel-isr-caching-post-requests-json-rpc/
If you're building APIs on Vercel, bookmark this one. It'll save you hours when you inevitably hit this issue.
Until next time, Colin
P.S. - If you've encountered similar Vercel gotchas, hit reply and let me know. Always looking for more topics to cover.