Skip to content
Merged
Show file tree
Hide file tree
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ A text-form relational graph covering:
| `ai-sdk` | AI SDK v6 — text/object generation, streaming, tool calling, agents, MCP, providers, embeddings |
| `auth` | Authentication integrations — Clerk, Descope, Auth0 setup for Next.js with Marketplace provisioning |
| `bootstrap` | Project bootstrapping orchestrator — linking, env provisioning, db setup, first-run commands |
| `cdn-caching` | Diagnose cache hit rate, stale content, revalidation behavior, and ISR read/write cost across CDN/ISR/PPR |
| `cdn-caching` | Diagnose cache hit rate, stale content, revalidation behavior, per-request cache reasons, and ISR read/write cost across CDN/ISR/PPR |
| `chat-sdk` | Multi-platform chat bots — Slack, Telegram, Teams, Discord, Google Chat, GitHub, Linear |
| `deployments-cicd` | Deployment and CI/CD — deploy, promote, rollback, --prebuilt, CI workflow files |
| `env-vars` | Environment variable management — .env files, vercel env commands, OIDC tokens |
Expand Down
2 changes: 1 addition & 1 deletion generated/build-from-skills.manifest.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"version": 1,
"generatedAt": "2026-07-01T19:14:58.838Z",
"generatedAt": "2026-07-07T17:26:07.851Z",
"templates": [
{
"template": "agents/ai-architect.md.tmpl",
Expand Down
2 changes: 1 addition & 1 deletion generated/skill-catalog.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Skill Catalog

> Auto-generated by `scripts/generate-catalog.ts` — do not edit manually.
> Generated: 2026-07-03T20:32:55.191Z
> Generated: 2026-07-06T20:39:13.075Z
> Skills: 30

## Table of Contents
Expand Down
56 changes: 53 additions & 3 deletions generated/skill-manifest.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"generatedAt": "2026-07-03T22:15:28.313Z",
"generatedAt": "2026-07-07T17:36:42.694Z",
"version": 2,
"skills": {
"ai-gateway": {
Expand Down Expand Up @@ -883,7 +883,15 @@
"isr read units",
"isr write units",
"stale content",
"x-vercel-cache"
"x-vercel-cache",
"cache reason",
"cacheReason",
"x-vercel-cache-reason",
"stale_time",
"stale_tag",
"stale_error",
"draft_mode",
"prerender_bypass"
],
"allOf": [
[
Expand All @@ -897,15 +905,57 @@
[
"revalidation",
"count"
],
[
"cache",
"reason"
],
[
"why",
"stale"
],
[
"why",
"bypass"
],
[
"cache",
"miss"
]
],
"anyOf": [
"revalidate",
"prerender",
"invalidate"
"invalidate",
"draft mode",
"crawler",
"cold cache",
"request collapsed"
],
"noneOf": [],
"minScore": 6
},
"retrieval": {
"aliases": [
"cache reason",
"cache hit rate",
"stale content"
],
"intents": [
"why is my page stale",
"why is this request a bypass",
"why was this a cache miss"
],
"entities": [
"cacheReason",
"collapsed",
"draft_mode",
"prerender_bypass",
"stale_time",
"stale_tag",
"stale_error"
],
"examples": []
}
},
"chat-sdk": {
Expand Down
53 changes: 51 additions & 2 deletions skills/cdn-caching/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: cdn-caching
description: Debug Vercel CDN caching — cache hit rate, stale content, revalidation behavior, ISR + PPR, and costs.
description: Debug Vercel CDN caching — cache hit rate, stale content, revalidation behavior, ISR + PPR, per-request cache reasons (cacheReason), and costs.
metadata:
priority: 6
docs:
Expand All @@ -18,15 +18,48 @@ metadata:
- 'isr write units'
- 'stale content'
- 'x-vercel-cache'
- 'cache reason'
- 'cacheReason'
- 'x-vercel-cache-reason'
- 'stale_time'
- 'stale_tag'
- 'stale_error'
- 'draft_mode'
- 'prerender_bypass'
allOf:
- [cache, debug]
- [stale, cache]
- [revalidation, count]
- [cache, reason]
- [why, stale]
- [why, bypass]
- [cache, miss]
anyOf:
- 'revalidate'
- 'prerender'
- 'invalidate'
- 'draft mode'
- 'crawler'
- 'cold cache'
- 'request collapsed'
minScore: 6
retrieval:
aliases:
- cache reason
- cache hit rate
- stale content
intents:
- why is my page stale
- why is this request a bypass
- why was this a cache miss
entities:
- cacheReason
- collapsed
- draft_mode
- prerender_bypass
- stale_time
- stale_tag
- stale_error
chainTo:
-
pattern: 'use cache|cacheLife|cacheTag'
Expand Down Expand Up @@ -65,7 +98,7 @@ Vercel caches at multiple layers between the visitor and your backend. A request
- _Invalidate_ (`invalidateByTag`, Next.js `revalidateTag`/`revalidatePath`) = stale-while-revalidate. Keeps serving stale while refreshing in the background → response shows `x-vercel-cache: STALE`.
- _Dangerously-delete_ (`dangerouslyDeleteByTag`, Next.js `updateTag` or a revalidate with no lifetime) = hard removal. The next request blocks in the **foreground** to regenerate → `x-vercel-cache: REVALIDATED`.
- **Cache tags & blast radius** — tags group cached entries so one call can clear many. A coarse tag attached to thousands of paths has a large _blast radius_: a single write drops them all and the hit rate collapses until they re-warm. Prefer granular tags (`product-${id}`) plus a roll-up tag.
- **Cache status / cache reason** (`x-vercel-cache` response header):
- **Cache status** (`x-vercel-cache` response header) — the _outcome_:

| Value | Meaning |
| ------------- | ---------------------------------------------------------------- |
Expand All @@ -76,6 +109,22 @@ Vercel caches at multiple layers between the visitor and your backend. A request
| `REVALIDATED` | Foreground revalidation after a delete (or `Pragma: no-cache`) |
| `BYPASS` | Caching skipped (`no-store`, `private`, cookies, etc.) |

- **Cache reason** (`cacheReason`) — the finer _explanation_ of that outcome for a single request. The `cache_result` metric lumps all `MISS`es (and all `STALE`s) together; the reason is the only thing that tells them apart. Nine values, three per group:

| `cacheReason` | Refines | Meaning |
| ------------------ | -------- | ----------------------------------------------------------------------------- |
| `cold` | MISS | Cache empty for this key/variant (first request or evicted); the function ran |
| `collapsed` | MISS | Concurrent requests to one uncached path collapsed into a single invocation |
| `error` | MISS | An error prevented serving from cache |
| `draft_mode` | → BYPASS | Next.js Draft Mode active — bypassed so editors see live content |
| `prerender_bypass` | → BYPASS | Prerender-bypass cookie/token present |
| `crawler` | → BYPASS | SEO-crawler UA — full response served so bots index real content |
| `stale_time` | STALE | Time-based `revalidate` interval elapsed; regenerating in background (SWR) |
| `stale_tag` | STALE | Tag invalidated (`revalidateTag` / `invalidateByTag`); regenerating |
| `stale_error` | STALE | A revalidation attempt **failed**; serving the last-good copy (a bug signal) |

A raw `MISS` with reason `draft_mode` / `prerender_bypass` / `crawler` is **displayed as `BYPASS`** (all usually expected). The three `stale_*` reasons separate a healthy time refresh (`stale_time`) from a broad-tag blast (`stale_tag`) from a failing regen (`stale_error`). Read `cacheReason` from `vercel logs` or the dashboard Logs "Reason" row — the `x-vercel-cache-reason` header is internal-only and not visible via `curl`.

## Investigating cache issues

Reach for the Vercel CLI. `vercel metrics` gives aggregate numbers (requires [Observability Plus](https://vercel.com/docs/observability/observability-plus)); `vercel logs` shows per-request behavior.
Expand Down
2 changes: 1 addition & 1 deletion vercel.md
Original file line number Diff line number Diff line change
Expand Up @@ -701,7 +701,7 @@ Three distinct caching systems serve different purposes. They can be used indepe

⤳ skill: runtime-cache — Per-region key-value caching with tag-based invalidation
⤳ skill: nextjs — `'use cache'`, `revalidatePath`, `revalidateTag`
⤳ skill: cdn-caching — Diagnose cache hit rate, stale content, and ISR read/write cost
⤳ skill: cdn-caching — Diagnose cache hit rate, stale content, per-request cache reasons, and ISR read/write cost

---

Expand Down
Loading