[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-vercel-cdn-caching":3,"mdc--p4rtl-key":34,"related-repo-vercel-cdn-caching":4099,"related-org-vercel-cdn-caching":4206},{"slug":4,"name":4,"fn":5,"description":6,"org":7,"tags":11,"stars":23,"repoUrl":24,"updatedAt":25,"license":26,"forks":27,"topics":28,"repo":29,"sourceUrl":32,"mdContent":33},"cdn-caching","debug Vercel CDN caching behavior","Debug Vercel CDN caching — cache hit rate, stale content, revalidation behavior, ISR + PPR, per-request cache reasons (cacheReason) and PPR state (ppr_state), and costs.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},"vercel","Vercel","https:\u002F\u002Fpexgzepcugksgbtrxkhf.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Forg-logos\u002Fvercel.png",[12,16,19,20],{"name":13,"slug":14,"type":15},"Observability","observability","tag",{"name":17,"slug":18,"type":15},"Performance","performance",{"name":9,"slug":8,"type":15},{"name":21,"slug":22,"type":15},"Caching","caching",226,"https:\u002F\u002Fgithub.com\u002Fvercel\u002Fvercel-plugin","2026-07-30T05:31:34.628944",null,36,[],{"repoUrl":24,"stars":23,"forks":27,"topics":30,"description":31},[],"Comprehensive Vercel ecosystem plugin — relational knowledge graph, skills for every major product, specialized agents, and Vercel conventions. Turns any AI agent into a Vercel expert.","https:\u002F\u002Fgithub.com\u002Fvercel\u002Fvercel-plugin\u002Ftree\u002FHEAD\u002Fskills\u002Fcdn-caching","---\nname: cdn-caching\ndescription: Debug Vercel CDN caching — cache hit rate, stale content, revalidation behavior, ISR + PPR, per-request cache reasons (cacheReason) and PPR state (ppr_state), and costs.\nmetadata:\n  priority: 6\n  docs:\n    - 'https:\u002F\u002Fvercel.com\u002Fdocs\u002Fcaching'\n    - 'https:\u002F\u002Fvercel.com\u002Fdocs\u002Fcaching\u002Fcdn-cache'\n    - 'https:\u002F\u002Fvercel.com\u002Fdocs\u002Fincremental-static-regeneration'\n    - 'https:\u002F\u002Fvercel.com\u002Fdocs\u002Fcli\u002Fmetrics'\n  bashPatterns:\n    - '\\bvercel\\s+cache\\s+(purge|invalidate|dangerously-delete)\\b'\n  promptSignals:\n    phrases:\n      - 'cache hit rate'\n      - 'isr cost'\n      - 'isr read units'\n      - 'isr write units'\n      - 'stale content'\n      - 'x-vercel-cache'\n      - 'cache reason'\n      - 'cacheReason'\n      - 'x-vercel-cache-reason'\n      - 'ppr state'\n      - 'ppr_state'\n      - 'x-vercel-ppr-state'\n      - 'stale_time'\n      - 'stale_tag'\n      - 'stale_error'\n      - 'draft_mode'\n      - 'prerender_bypass'\n    allOf:\n      - [cache, debug]\n      - [stale, cache]\n      - [revalidation, count]\n      - [cache, reason]\n      - [why, stale]\n      - [why, bypass]\n      - [cache, miss]\n    anyOf:\n      - 'revalidate'\n      - 'prerender'\n      - 'invalidate'\n      - 'draft mode'\n      - 'crawler'\n      - 'cold cache'\n      - 'request collapsed'\n    minScore: 6\nretrieval:\n  aliases:\n    - cache reason\n    - ppr state\n    - cache hit rate\n    - stale content\n  intents:\n    - why is my page stale\n    - why is this request a bypass\n    - why was this a cache miss\n  entities:\n    - cacheReason\n    - ppr_state\n    - collapsed\n    - draft_mode\n    - prerender_bypass\n    - stale_time\n    - stale_tag\n    - stale_error\nchainTo:\n  -\n    pattern: 'use cache|cacheLife|cacheTag'\n    targetSkill: next-cache-components\n    message: 'Next.js cache directives detected — loading Cache Components guidance for revalidate\u002Ftag tuning.'\n---\n\n# Vercel Caching\n\nYou are an expert in understanding Vercel's caching infrastructure, and how the CDN Cache, ISR, and PPR work.\n\n## Core Knowledge\n\n- ISR (and PPR, a rendering strategy built on it) is a framework feature — Next.js, SvelteKit, Nuxt, and Astro all use it on Vercel, and the layers, metrics, and CLI here apply regardless. (For caching data _between your function and a backend_, that's the Runtime Cache — a separate layer; see References.)\n- **PPR (Partial Prerendering)** — a rendering strategy, _not_ a cache layer: the static shell lives in the **ISR cache** while a function renders the dynamic holes per request and streams them into the same response. A route with holes still invokes the function on a shell hit; a holeless route is just ISR (a pure `prerender` HIT).\n\n### How caching works\n\nVercel caches at multiple layers between the visitor and your backend. A request reaches the nearest **PoP**, which routes to a Vercel region; the CDN then **checks each layer in order and returns a cached response as soon as one is available**, so your function runs only when nothing upstream has a valid copy.\n\n#### Cache layers\n\n- **CDN cache** — regional, ephemeral. On a hit the region returns the response with no function call. Reads\u002Fwrites are **free**.\n- **ISR cache** — durable, in a single [Function region](https:\u002F\u002Fvercel.com\u002Fdocs\u002Ffunctions\u002Fconfiguring-functions\u002Fregion). On a CDN miss, Vercel reads here _before_ invoking your function (cache shielding), then replicates the result back to the CDN. Survives deploys for 31 days or until revalidated; reads\u002Fwrites are **billed in 8 KB units**.\n- **Function invocation** — runs only if neither cache has a valid copy. It may read the Runtime\u002Fdata cache (a separate layer; see References) and your backend, then Vercel stores the response in the ISR cache.\n- **Image cache** — optimized images, cached on the CDN after the first transform.\n- Purges propagate globally in ~300 ms.\n\n**Request collapsing**: when many requests hit the same uncached path at once, Vercel collapses them into one function invocation per region to protect the origin.\n\n#### Key concepts\n\n- **Cache hit rate** — share served from cache (`HIT`\u002F`STALE`\u002F`PRERENDER`) versus origin (`MISS`\u002F`REVALIDATED`). Measure it over _cacheable_ requests — exclude `BYPASS` and `(not set)` (redirects, errors, uncacheable methods), or they drag the ratio down for non-cache reasons. Low hit rate means more origin load and higher latency.\n- **Revalidation** — refreshing cached content. **Time-based** runs automatically after an interval; **on-demand** runs when you call an API. Both use stale-while-revalidate: visitors keep getting the cached version while the new one regenerates in the background.\n- **Invalidate vs. dangerously-delete** — two ways to clear content, with very different blast on hit rate:\n  - _Invalidate_ (`invalidateByTag`, Next.js `revalidateTag`\u002F`revalidatePath`) = stale-while-revalidate. Keeps serving stale while refreshing in the background → response shows `x-vercel-cache: STALE`.\n  - _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`.\n- **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.\n- **Cache status** (`x-vercel-cache` response header) — the _outcome_:\n\n  | Value         | Meaning                                                          |\n  | ------------- | ---------------------------------------------------------------- |\n  | `HIT`         | Served from cache; no function ran                               |\n  | `MISS`        | Not cached; origin\u002Ffunction ran                                  |\n  | `STALE`       | Served stale while revalidating in background (SWR \u002F invalidate) |\n  | `PRERENDER`   | Served a prerendered ISR\u002FPPR shell                               |\n  | `REVALIDATED` | Foreground revalidation after a delete (or `Pragma: no-cache`)   |\n  | `BYPASS`      | Caching skipped (`no-store`, `private`, cookies, etc.)           |\n\n- **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:\n\n  | `cacheReason`      | Refines  | Meaning                                                                       |\n  | ------------------ | -------- | ----------------------------------------------------------------------------- |\n  | `cold`             | MISS     | Cache empty for this key\u002Fvariant (first request or evicted); the function ran |\n  | `collapsed`        | MISS     | Concurrent requests to one uncached path collapsed into a single invocation   |\n  | `error`            | MISS     | An error prevented serving from cache                                         |\n  | `draft_mode`       | → BYPASS | Next.js Draft Mode active — bypassed so editors see live content              |\n  | `prerender_bypass` | → BYPASS | Prerender-bypass cookie\u002Ftoken present                                         |\n  | `crawler`          | → BYPASS | SEO-crawler UA — full response served so bots index real content              |\n  | `stale_time`       | STALE    | Time-based `revalidate` interval elapsed; regenerating in background (SWR)     |\n  | `stale_tag`        | STALE    | Tag invalidated (`revalidateTag` \u002F `invalidateByTag`); regenerating           |\n  | `stale_error`      | STALE    | A revalidation attempt **failed**; serving the last-good copy (a bug signal)  |\n\n  A raw `MISS` with reason `draft_mode` \u002F `prerender_bypass` \u002F `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`.\n\n- **PPR state** (`ppr_state`) — for a Partial Prerendering route, _how much_ of the response was prerendered versus computed per request. Only set on `partial_prerender` serves; blank for plain `prerender` \u002F `func` \u002F `static` routes and for cases the proxy can't classify (cold shell miss, `BYPASS`). Three values:\n\n  | `ppr_state` | Shown as | Meaning                                                                             |\n  | ----------- | -------- | ----------------------------------------------------------------------------------- |\n  | `page`      | Static   | Fully prerendered — no postponed state, so the function is not invoked for the body |\n  | `shell`     | Partial  | Non-empty static shell from cache + a postponed hole the function resumes per request |\n  | `blocking`  | Dynamic  | Empty shell — the whole body is postponed and rendered by the function per request  |\n\n  A shell hit that still invokes the function is `shell` (Partial), _not_ a cache miss — the cached shell serves immediately while the function fills only the dynamic holes. Read `ppr_state` from `vercel logs` or the dashboard Logs panel, or aggregate with `vercel metrics vercel.request.count --group-by ppr_state`. Like `cacheReason`, the `x-vercel-ppr-state` header is internal-only and not visible via `curl`.\n\n## Investigating cache issues\n\nReach for the Vercel CLI. `vercel metrics` gives aggregate numbers (requires [Observability Plus](https:\u002F\u002Fvercel.com\u002Fdocs\u002Fobservability\u002Fobservability-plus)); `vercel logs` shows per-request behavior.\n\nMetrics need to be queried by team and project (`-S \u003Cteam> -p \u003Cproject>`). Filter production with `-f \"environment eq 'production'\"` (there is no `--prod` flag). Run `vercel metrics schema \u003Cmetric>` to discover dimensions; use `-F json` for machine-readable output. With `-g`, remember **`--limit` is per time bucket** — omit `-g` when you need totals across the whole window.\n\n### Cache hit rate\n\nStart here for an overall picture of how well caching is working.\n\n**Step 1 — overall split.** Group `vercel.request.count` by `cache_result`. Treat `HIT`, `STALE`, and `PRERENDER` as cache-served; focus investigation on `MISS`. Exclude `BYPASS` and `(not set)` when computing a hit rate over _cacheable_ traffic (see [Debugging BYPASS traffic](#debugging-bypass-traffic)). `STALE` means stale-while-revalidate is working — dig into revalidation frequency in [Analyzing ISR costs](#analyzing-isr-costs), not here.\n\n```bash\nvercel metrics vercel.request.count -S \u003Cteam> -p \u003Cproject> \\\n  -f \"environment eq 'production'\" --group-by cache_result --since 24h\n```\n\n**Step 2 — where misses concentrate.** Split the `MISS` bucket (and optionally `STALE`) by `path_type`, then by `route` or `request_path`:\n\n```bash\nvercel metrics vercel.request.count -S \u003Cteam> -p \u003Cproject> \\\n  -f \"environment eq 'production' and cache_result eq 'MISS'\" \\\n  --group-by path_type --since 24h\n\nvercel metrics vercel.request.count -S \u003Cteam> -p \u003Cproject> \\\n  -f \"environment eq 'production' and cache_result eq 'MISS' and path_type eq 'prerender'\" \\\n  --group-by request_path --since 24h\n```\n\n**What to expect:** `prerender` routes (static shells, ISR pages) should show a high share of `HIT`\u002F`PRERENDER`. A `prerender` path with a disproportionate `MISS` count is your short list for per-path header inspection (`curl` above) and code review.\n\n`streaming_func` routes render dynamically by default, but you can still cache them with `Cache-Control` headers — matching requests are cached on the CDN. Each cache entry varies by `Vary` headers (cookies, RSC, etc.) as well as path and query parameters, so expect more cache keys and a lower hit rate than a fully static `prerender` route.\n\n### Analyzing ISR costs\n\nOnce you know hit rate, quantify ISR spend and whether revalidation — not traffic volume — is driving it.\n\n**Utilization vs. ISR billing.** **Utilization** is `vercel.request.count` — total request volume. **ISR cost** is billed separately in 8 KB units: `read_units` when the regional CDN misses and falls through to the ISR cache, and `write_units` on every revalidation\u002Fregeneration. The regional CDN shields ISR heavily — most requests never touch the ISR layer, so **read_units will be far below request count**. Do not compare read_units to write_units as a utilization check; focus on **write_units** (revalidation cost) and how they relate to total traffic.\n\n```bash\nvercel metrics vercel.request.count -S \u003Cteam> -p \u003Cproject> -a sum --since 24h\nvercel metrics vercel.isr_operation.write_units -S \u003Cteam> -p \u003Cproject> -a sum --since 24h\n```\n\n**Write utilization = cache serves ÷ ISR writes** — cached reads per regeneration.\n\n```bash\n# numerator: cache serves — sum the HIT + STALE + PRERENDER buckets\nvercel metrics vercel.request.count -S \u003Cteam> -p \u003Cproject> \\\n  -f \"environment eq 'production' and (cache_result eq 'HIT' or cache_result eq 'STALE')\" \\\n  --group-by route -a sum --since 24h\n# denominator: ISR writes\nvercel metrics vercel.isr_operation.write_units -S \u003Cteam> -p \u003Cproject> \\\n  -f \"environment eq 'production'\" --group-by route -a sum --since 24h\n```\n\nHigh is good; near or below ~1 means you regenerate about as fast as the page is read (wasted writes) → lengthen the revalidate interval or move time-based to on-demand tag revalidation.\n\n**Which routes revalidate most.** Break write units down by `route` and `request_path` to find paths that regenerate often relative to traffic:\n\n```bash\nvercel metrics vercel.isr_operation.write_units -S \u003Cteam> -p \u003Cproject> \\\n  -a sum --group-by route --since 24h\n\nvercel metrics vercel.isr_operation.write_units -S \u003Cteam> -p \u003Cproject> \\\n  -a sum --group-by request_path --since 24h\n```\n\n**Regeneration vs. serving.** Group write units by `path_type` — concentration in `background_func` confirms revalidation (not per-request dynamic work) is the cost driver.\n\n**Time-based vs. tag-based revalidation.** Time-based intervals regenerate on a schedule whether or not content changed — often inefficient. Tag-based on-demand revalidation is usually better, but an **overly broad tag** has a large blast radius: one invalidate drops every entry that carries it.\n\n- **Tag blast radius** — group write units by `cache_tags`. If many _unrelated_ routes show near-identical write counts, a shared hot tag is invalidating them in lockstep (e.g. every blog post rewriting at the same rate because they share one broad `blogPost` tag):\n\n```bash\nvercel metrics vercel.isr_operation.write_units -S \u003Cteam> -p \u003Cproject> \\\n  -a sum --group-by cache_tags --since 24h\n```\n\n- **What triggered revalidation** — group `vercel.request.count` by `triggering_tag` to see which tags fire most often (`triggering_tag` is on request count only, not ISR operation metrics. It is one of the tags that triggered the page to be stale):\n\n```bash\nvercel metrics vercel.request.count -S \u003Cteam> -p \u003Cproject> \\\n  -f \"triggering_tag ne null\" --group-by triggering_tag --since 24h\n```\n\nTags with a large blast radius that revalidate frequently are the usual root cause of high write_units. Prefer granular tags (`product-${id}`) and on-demand invalidation over short time-based intervals for event-driven content.\n\n**Confirm in code.** Metrics tell you _which_ tag is hot; the repo tells you _why_. Grep for the tag's invalidation call site — `revalidateTag(`, `invalidateByTag(`, `updateTag(`, `dangerouslyDeleteByTag(` — and read the trigger. A CMS webhook or a sync cron that invalidates a **broad** tag on every event (instead of a specific `${type}:${id}`) is the classic amplifier.\n\n### Debugging BYPASS traffic\n\nThe largest legitimate sources of `BYPASS` are **Draft Mode** and **SEO crawlers**. Draft Mode must bypass cache so editors see live content. SEO bots must receive the **full response** — especially on PPR routes where the static shell and dynamic holes are assembled at request time — so crawlers index what users actually see. That BYPASS is expected, not a misconfiguration.\n\nBefore tuning headers or revalidate intervals, confirm what's left after those two buckets:\n\n```bash\nvercel metrics vercel.request.count -S \u003Cteam> -p \u003Cproject> \\\n  -f \"cache_result eq 'BYPASS'\" --group-by bot_category --since 24h\n\nvercel metrics vercel.request.count -S \u003Cteam> -p \u003Cproject> \\\n  -f \"cache_result eq 'BYPASS'\" --group-by user_agent --since 24h\n\nvercel metrics vercel.request.count -S \u003Cteam> -p \u003Cproject> \\\n  -f \"cache_result eq 'BYPASS'\" --group-by request_method --since 24h\n```\n\nThe **Firewall\u002FWAF** with the `vercel-firewall` skill can be used to manage verified SEO crawlers, block abusive bots, and rate-limit junk traffic before it distorts your hit-rate picture.\n\n## Reducing ISR cost\n\n- **Prefer tag-based over time-based revalidation.** Replace short `revalidate` intervals with on-demand `revalidateTag` \u002F `invalidateByTag` when content changes — time-based regeneration runs whether or not anything changed. If using Cache Components, analyze `cacheLife` calls with the `next-cache-components` skill.\n- **Scope tags to specific IDs.** Invalidate `blogPost:\u003Cid>`, not a generic `blogPost`\u002F`page` tag — one broad invalidate regenerates everything that carries it.\n- Tune the revalidate interval where your framework declares it (Next.js `revalidate` \u002F `cacheLife`, SvelteKit `isr`, Nuxt `routeRules`, Astro). For Next.js Cache Components, see the `next-cache-components` skill.\n- Use `CDN-Cache-Control` headers to cache dynamic functions.\n\n### Inspect one path\n\n```bash\ncurl -sSI https:\u002F\u002F\u003Chost>\u002F\u003Cpath> | grep -iE 'x-vercel-cache|x-matched-path|cache-control|vary|age|set-cookie'\n```\n\nThis zero-dependency first reach shows the status (`x-vercel-cache`), the cache directives (`Cache-Control` \u002F `CDN-Cache-Control` \u002F `Vercel-CDN-Cache-Control`), and — crucially — **`x-matched-path`**, which reveals rewrites like `\u002Fprecomputed\u002Fexp~...\u002F...` that expose experiment\u002Fflag precomputation. `vary` flags personalization (RSC, cookies); `set-cookie` forces `BYPASS`. For a per-phase timing breakdown, `vercel httpstat \u002Fsome\u002Fpath` (CLI v48.9.0+; needs the `httpstat` tool installed) adds latency stats. A path that should cache but shows `MISS`\u002F`BYPASS` usually has `private`, `no-store`, `max-age=0`, a per-request input (cookies\u002Fheaders\u002F`searchParams`), or an uncacheable method (see FAQ).\n\n**Inspect one request.** When metrics or headers give you a request ID, pull the full log record:\n\n```bash\nvercel logs --request-id \u003Crequest-id> --json\n```\n\nUse `--json` so the agent can parse cache status, path, and timing fields programmatically.\n\n## FAQ\n\n- **What are prerender variant misses?** When a route uses a dynamic param, each distinct cache-key variant is prerendered and cached separately, so each variant misses on its first hit per region and low-traffic ones rarely stay warm. The most common modern cause is **feature-flag \u002F experiment precomputation** — middleware picks a variant per request (`\u002Fprecomputed\u002Fexp~...\u002F...` paths), and flags × routes × PPR segments multiply into thousands of ISR entries (also a middleware-invocation cost). Fix: collapse the variant matrix (retire finished experiments), or accept the cost.\n- **Does PPR avoid function invocations?** No — a PPR route has dynamic holes by definition, so the cached shell hit still runs the function to fill them. (A route with _no_ holes is just ISR and serves a pure `prerender` HIT — see Key concepts.)\n- **Why are there more function invocations than PPR requests?** PPR requests have a static shell and a dynamic function invocation. When the static shell needs to be regenerated, it incurs a function invocation on top of the dynamic function for the content.\n\n## Related skills\n\n- `vercel-firewall` — manage verified SEO crawlers, block abusive bots, and rate-limit junk BYPASS traffic.\n- `runtime-cache` — caching data _between your function and a backend_ (per-region key-value \u002F data cache). A different layer from the CDN\u002FISR caches; use it to cache an API response or query result inside a function.\n- `next-cache-components` — Next.js `use cache`, `cacheLife`, `cacheTag`, and `revalidate` tuning (one framework's ISR\u002FPPR controls).\n\n## References:\n\n- Caching overview: https:\u002F\u002Fvercel.com\u002Fdocs\u002Fcaching\n- ISR: https:\u002F\u002Fvercel.com\u002Fdocs\u002Fincremental-static-regeneration\n- Partial Prerendering (PPR): https:\u002F\u002Fvercel.com\u002Fdocs\u002Fpartial-prerendering\n- Cache-Control headers: https:\u002F\u002Fvercel.com\u002Fdocs\u002Fcaching\u002Fcache-control-headers\n- Diagnosing and fixing cache issues (full runbook): https:\u002F\u002Fvercel.com\u002Fdocs\u002Fcaching\u002Fcdn-cache\u002Fdebug-cache-issues\n- vercel metrics CLI: https:\u002F\u002Fvercel.com\u002Fdocs\u002Fcli\u002Fmetrics\n- vercel logs CLI: https:\u002F\u002Fvercel.com\u002Fdocs\u002Fcli\u002Flogs\n",{"data":35,"body":102},{"name":4,"description":6,"metadata":36,"retrieval":89,"chainTo":97},{"priority":37,"docs":38,"bashPatterns":43,"promptSignals":45},6,[39,40,41,42],"https:\u002F\u002Fvercel.com\u002Fdocs\u002Fcaching","https:\u002F\u002Fvercel.com\u002Fdocs\u002Fcaching\u002Fcdn-cache","https:\u002F\u002Fvercel.com\u002Fdocs\u002Fincremental-static-regeneration","https:\u002F\u002Fvercel.com\u002Fdocs\u002Fcli\u002Fmetrics",[44],"\\bvercel\\s+cache\\s+(purge|invalidate|dangerously-delete)\\b",{"phrases":46,"allOf":64,"anyOf":81,"minScore":37},[47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63],"cache hit rate","isr cost","isr read units","isr write units","stale content","x-vercel-cache","cache reason","cacheReason","x-vercel-cache-reason","ppr state","ppr_state","x-vercel-ppr-state","stale_time","stale_tag","stale_error","draft_mode","prerender_bypass",[65,68,70,73,75,77,79],[66,67],"cache","debug",[69,66],"stale",[71,72],"revalidation","count",[66,74],"reason",[76,69],"why",[76,78],"bypass",[66,80],"miss",[82,83,84,85,86,87,88],"revalidate","prerender","invalidate","draft mode","crawler","cold cache","request collapsed",{"aliases":90,"intents":91,"entities":95},[53,56,47,51],[92,93,94],"why is my page stale","why is this request a bypass","why was this a cache miss",[54,57,96,62,63,59,60,61],"collapsed",[98],{"pattern":99,"targetSkill":100,"message":101},"use cache|cacheLife|cacheTag","next-cache-components","Next.js cache directives detected — loading Cache Components guidance for revalidate\u002Ftag tuning.",{"type":103,"children":104},"root",[105,114,120,127,178,185,204,211,289,299,305,1289,1295,1324,1397,1402,1407,1501,1633,1680,1907,1958,1992,1997,2002,2060,2212,2222,2459,2464,2487,2674,2699,2716,2752,2846,2880,2983,2995,3062,3067,3099,3104,3412,3432,3438,3570,3576,3670,3801,3811,3858,3870,3876,3937,3943,4010,4016,4093],{"type":106,"tag":107,"props":108,"children":110},"element","h1",{"id":109},"vercel-caching",[111],{"type":112,"value":113},"text","Vercel Caching",{"type":106,"tag":115,"props":116,"children":117},"p",{},[118],{"type":112,"value":119},"You are an expert in understanding Vercel's caching infrastructure, and how the CDN Cache, ISR, and PPR work.",{"type":106,"tag":121,"props":122,"children":124},"h2",{"id":123},"core-knowledge",[125],{"type":112,"value":126},"Core Knowledge",{"type":106,"tag":128,"props":129,"children":130},"ul",{},[131,145],{"type":106,"tag":132,"props":133,"children":134},"li",{},[135,137,143],{"type":112,"value":136},"ISR (and PPR, a rendering strategy built on it) is a framework feature — Next.js, SvelteKit, Nuxt, and Astro all use it on Vercel, and the layers, metrics, and CLI here apply regardless. (For caching data ",{"type":106,"tag":138,"props":139,"children":140},"em",{},[141],{"type":112,"value":142},"between your function and a backend",{"type":112,"value":144},", that's the Runtime Cache — a separate layer; see References.)",{"type":106,"tag":132,"props":146,"children":147},{},[148,154,156,161,163,168,170,176],{"type":106,"tag":149,"props":150,"children":151},"strong",{},[152],{"type":112,"value":153},"PPR (Partial Prerendering)",{"type":112,"value":155}," — a rendering strategy, ",{"type":106,"tag":138,"props":157,"children":158},{},[159],{"type":112,"value":160},"not",{"type":112,"value":162}," a cache layer: the static shell lives in the ",{"type":106,"tag":149,"props":164,"children":165},{},[166],{"type":112,"value":167},"ISR cache",{"type":112,"value":169}," while a function renders the dynamic holes per request and streams them into the same response. A route with holes still invokes the function on a shell hit; a holeless route is just ISR (a pure ",{"type":106,"tag":171,"props":172,"children":174},"code",{"className":173},[],[175],{"type":112,"value":83},{"type":112,"value":177}," HIT).",{"type":106,"tag":179,"props":180,"children":182},"h3",{"id":181},"how-caching-works",[183],{"type":112,"value":184},"How caching works",{"type":106,"tag":115,"props":186,"children":187},{},[188,190,195,197,202],{"type":112,"value":189},"Vercel caches at multiple layers between the visitor and your backend. A request reaches the nearest ",{"type":106,"tag":149,"props":191,"children":192},{},[193],{"type":112,"value":194},"PoP",{"type":112,"value":196},", which routes to a Vercel region; the CDN then ",{"type":106,"tag":149,"props":198,"children":199},{},[200],{"type":112,"value":201},"checks each layer in order and returns a cached response as soon as one is available",{"type":112,"value":203},", so your function runs only when nothing upstream has a valid copy.",{"type":106,"tag":205,"props":206,"children":208},"h4",{"id":207},"cache-layers",[209],{"type":112,"value":210},"Cache layers",{"type":106,"tag":128,"props":212,"children":213},{},[214,231,264,274,284],{"type":106,"tag":132,"props":215,"children":216},{},[217,222,224,229],{"type":106,"tag":149,"props":218,"children":219},{},[220],{"type":112,"value":221},"CDN cache",{"type":112,"value":223}," — regional, ephemeral. On a hit the region returns the response with no function call. Reads\u002Fwrites are ",{"type":106,"tag":149,"props":225,"children":226},{},[227],{"type":112,"value":228},"free",{"type":112,"value":230},".",{"type":106,"tag":132,"props":232,"children":233},{},[234,238,240,249,251,256,258,263],{"type":106,"tag":149,"props":235,"children":236},{},[237],{"type":112,"value":167},{"type":112,"value":239}," — durable, in a single ",{"type":106,"tag":241,"props":242,"children":246},"a",{"href":243,"rel":244},"https:\u002F\u002Fvercel.com\u002Fdocs\u002Ffunctions\u002Fconfiguring-functions\u002Fregion",[245],"nofollow",[247],{"type":112,"value":248},"Function region",{"type":112,"value":250},". On a CDN miss, Vercel reads here ",{"type":106,"tag":138,"props":252,"children":253},{},[254],{"type":112,"value":255},"before",{"type":112,"value":257}," invoking your function (cache shielding), then replicates the result back to the CDN. Survives deploys for 31 days or until revalidated; reads\u002Fwrites are ",{"type":106,"tag":149,"props":259,"children":260},{},[261],{"type":112,"value":262},"billed in 8 KB units",{"type":112,"value":230},{"type":106,"tag":132,"props":265,"children":266},{},[267,272],{"type":106,"tag":149,"props":268,"children":269},{},[270],{"type":112,"value":271},"Function invocation",{"type":112,"value":273}," — runs only if neither cache has a valid copy. It may read the Runtime\u002Fdata cache (a separate layer; see References) and your backend, then Vercel stores the response in the ISR cache.",{"type":106,"tag":132,"props":275,"children":276},{},[277,282],{"type":106,"tag":149,"props":278,"children":279},{},[280],{"type":112,"value":281},"Image cache",{"type":112,"value":283}," — optimized images, cached on the CDN after the first transform.",{"type":106,"tag":132,"props":285,"children":286},{},[287],{"type":112,"value":288},"Purges propagate globally in ~300 ms.",{"type":106,"tag":115,"props":290,"children":291},{},[292,297],{"type":106,"tag":149,"props":293,"children":294},{},[295],{"type":112,"value":296},"Request collapsing",{"type":112,"value":298},": when many requests hit the same uncached path at once, Vercel collapses them into one function invocation per region to protect the origin.",{"type":106,"tag":205,"props":300,"children":302},{"id":301},"key-concepts",[303],{"type":112,"value":304},"Key concepts",{"type":106,"tag":128,"props":306,"children":307},{},[308,379,403,494,519,690,1077],{"type":106,"tag":132,"props":309,"children":310},{},[311,316,318,324,326,332,333,339,341,347,348,354,356,361,363,369,371,377],{"type":106,"tag":149,"props":312,"children":313},{},[314],{"type":112,"value":315},"Cache hit rate",{"type":112,"value":317}," — share served from cache (",{"type":106,"tag":171,"props":319,"children":321},{"className":320},[],[322],{"type":112,"value":323},"HIT",{"type":112,"value":325},"\u002F",{"type":106,"tag":171,"props":327,"children":329},{"className":328},[],[330],{"type":112,"value":331},"STALE",{"type":112,"value":325},{"type":106,"tag":171,"props":334,"children":336},{"className":335},[],[337],{"type":112,"value":338},"PRERENDER",{"type":112,"value":340},") versus origin (",{"type":106,"tag":171,"props":342,"children":344},{"className":343},[],[345],{"type":112,"value":346},"MISS",{"type":112,"value":325},{"type":106,"tag":171,"props":349,"children":351},{"className":350},[],[352],{"type":112,"value":353},"REVALIDATED",{"type":112,"value":355},"). Measure it over ",{"type":106,"tag":138,"props":357,"children":358},{},[359],{"type":112,"value":360},"cacheable",{"type":112,"value":362}," requests — exclude ",{"type":106,"tag":171,"props":364,"children":366},{"className":365},[],[367],{"type":112,"value":368},"BYPASS",{"type":112,"value":370}," and ",{"type":106,"tag":171,"props":372,"children":374},{"className":373},[],[375],{"type":112,"value":376},"(not set)",{"type":112,"value":378}," (redirects, errors, uncacheable methods), or they drag the ratio down for non-cache reasons. Low hit rate means more origin load and higher latency.",{"type":106,"tag":132,"props":380,"children":381},{},[382,387,389,394,396,401],{"type":106,"tag":149,"props":383,"children":384},{},[385],{"type":112,"value":386},"Revalidation",{"type":112,"value":388}," — refreshing cached content. ",{"type":106,"tag":149,"props":390,"children":391},{},[392],{"type":112,"value":393},"Time-based",{"type":112,"value":395}," runs automatically after an interval; ",{"type":106,"tag":149,"props":397,"children":398},{},[399],{"type":112,"value":400},"on-demand",{"type":112,"value":402}," runs when you call an API. Both use stale-while-revalidate: visitors keep getting the cached version while the new one regenerates in the background.",{"type":106,"tag":132,"props":404,"children":405},{},[406,411,413],{"type":106,"tag":149,"props":407,"children":408},{},[409],{"type":112,"value":410},"Invalidate vs. dangerously-delete",{"type":112,"value":412}," — two ways to clear content, with very different blast on hit rate:",{"type":106,"tag":128,"props":414,"children":415},{},[416,456],{"type":106,"tag":132,"props":417,"children":418},{},[419,424,426,432,434,440,441,447,449,455],{"type":106,"tag":138,"props":420,"children":421},{},[422],{"type":112,"value":423},"Invalidate",{"type":112,"value":425}," (",{"type":106,"tag":171,"props":427,"children":429},{"className":428},[],[430],{"type":112,"value":431},"invalidateByTag",{"type":112,"value":433},", Next.js ",{"type":106,"tag":171,"props":435,"children":437},{"className":436},[],[438],{"type":112,"value":439},"revalidateTag",{"type":112,"value":325},{"type":106,"tag":171,"props":442,"children":444},{"className":443},[],[445],{"type":112,"value":446},"revalidatePath",{"type":112,"value":448},") = stale-while-revalidate. Keeps serving stale while refreshing in the background → response shows ",{"type":106,"tag":171,"props":450,"children":452},{"className":451},[],[453],{"type":112,"value":454},"x-vercel-cache: STALE",{"type":112,"value":230},{"type":106,"tag":132,"props":457,"children":458},{},[459,464,465,471,472,478,480,485,487,493],{"type":106,"tag":138,"props":460,"children":461},{},[462],{"type":112,"value":463},"Dangerously-delete",{"type":112,"value":425},{"type":106,"tag":171,"props":466,"children":468},{"className":467},[],[469],{"type":112,"value":470},"dangerouslyDeleteByTag",{"type":112,"value":433},{"type":106,"tag":171,"props":473,"children":475},{"className":474},[],[476],{"type":112,"value":477},"updateTag",{"type":112,"value":479}," or a revalidate with no lifetime) = hard removal. The next request blocks in the ",{"type":106,"tag":149,"props":481,"children":482},{},[483],{"type":112,"value":484},"foreground",{"type":112,"value":486}," to regenerate → ",{"type":106,"tag":171,"props":488,"children":490},{"className":489},[],[491],{"type":112,"value":492},"x-vercel-cache: REVALIDATED",{"type":112,"value":230},{"type":106,"tag":132,"props":495,"children":496},{},[497,502,504,509,511,517],{"type":106,"tag":149,"props":498,"children":499},{},[500],{"type":112,"value":501},"Cache tags & blast radius",{"type":112,"value":503}," — tags group cached entries so one call can clear many. A coarse tag attached to thousands of paths has a large ",{"type":106,"tag":138,"props":505,"children":506},{},[507],{"type":112,"value":508},"blast radius",{"type":112,"value":510},": a single write drops them all and the hit rate collapses until they re-warm. Prefer granular tags (",{"type":106,"tag":171,"props":512,"children":514},{"className":513},[],[515],{"type":112,"value":516},"product-${id}",{"type":112,"value":518},") plus a roll-up tag.",{"type":106,"tag":132,"props":520,"children":521},{},[522,527,528,533,535,540,542],{"type":106,"tag":149,"props":523,"children":524},{},[525],{"type":112,"value":526},"Cache status",{"type":112,"value":425},{"type":106,"tag":171,"props":529,"children":531},{"className":530},[],[532],{"type":112,"value":52},{"type":112,"value":534}," response header) — the ",{"type":106,"tag":138,"props":536,"children":537},{},[538],{"type":112,"value":539},"outcome",{"type":112,"value":541},":",{"type":106,"tag":543,"props":544,"children":545},"table",{},[546,565],{"type":106,"tag":547,"props":548,"children":549},"thead",{},[550],{"type":106,"tag":551,"props":552,"children":553},"tr",{},[554,560],{"type":106,"tag":555,"props":556,"children":557},"th",{},[558],{"type":112,"value":559},"Value",{"type":106,"tag":555,"props":561,"children":562},{},[563],{"type":112,"value":564},"Meaning",{"type":106,"tag":566,"props":567,"children":568},"tbody",{},[569,586,602,618,634,658],{"type":106,"tag":551,"props":570,"children":571},{},[572,581],{"type":106,"tag":573,"props":574,"children":575},"td",{},[576],{"type":106,"tag":171,"props":577,"children":579},{"className":578},[],[580],{"type":112,"value":323},{"type":106,"tag":573,"props":582,"children":583},{},[584],{"type":112,"value":585},"Served from cache; no function ran",{"type":106,"tag":551,"props":587,"children":588},{},[589,597],{"type":106,"tag":573,"props":590,"children":591},{},[592],{"type":106,"tag":171,"props":593,"children":595},{"className":594},[],[596],{"type":112,"value":346},{"type":106,"tag":573,"props":598,"children":599},{},[600],{"type":112,"value":601},"Not cached; origin\u002Ffunction ran",{"type":106,"tag":551,"props":603,"children":604},{},[605,613],{"type":106,"tag":573,"props":606,"children":607},{},[608],{"type":106,"tag":171,"props":609,"children":611},{"className":610},[],[612],{"type":112,"value":331},{"type":106,"tag":573,"props":614,"children":615},{},[616],{"type":112,"value":617},"Served stale while revalidating in background (SWR \u002F invalidate)",{"type":106,"tag":551,"props":619,"children":620},{},[621,629],{"type":106,"tag":573,"props":622,"children":623},{},[624],{"type":106,"tag":171,"props":625,"children":627},{"className":626},[],[628],{"type":112,"value":338},{"type":106,"tag":573,"props":630,"children":631},{},[632],{"type":112,"value":633},"Served a prerendered ISR\u002FPPR shell",{"type":106,"tag":551,"props":635,"children":636},{},[637,645],{"type":106,"tag":573,"props":638,"children":639},{},[640],{"type":106,"tag":171,"props":641,"children":643},{"className":642},[],[644],{"type":112,"value":353},{"type":106,"tag":573,"props":646,"children":647},{},[648,650,656],{"type":112,"value":649},"Foreground revalidation after a delete (or ",{"type":106,"tag":171,"props":651,"children":653},{"className":652},[],[654],{"type":112,"value":655},"Pragma: no-cache",{"type":112,"value":657},")",{"type":106,"tag":551,"props":659,"children":660},{},[661,669],{"type":106,"tag":573,"props":662,"children":663},{},[664],{"type":106,"tag":171,"props":665,"children":667},{"className":666},[],[668],{"type":112,"value":368},{"type":106,"tag":573,"props":670,"children":671},{},[672,674,680,682,688],{"type":112,"value":673},"Caching skipped (",{"type":106,"tag":171,"props":675,"children":677},{"className":676},[],[678],{"type":112,"value":679},"no-store",{"type":112,"value":681},", ",{"type":106,"tag":171,"props":683,"children":685},{"className":684},[],[686],{"type":112,"value":687},"private",{"type":112,"value":689},", cookies, etc.)",{"type":106,"tag":132,"props":691,"children":692},{},[693,698,699,704,706,711,713,719,721,726,728,733,735,975,979,981,986,988,993,994,999,1000,1005,1007,1017,1019,1025,1027,1032,1034,1039,1041,1046,1048,1053,1055,1061,1063,1068,1070,1076],{"type":106,"tag":149,"props":694,"children":695},{},[696],{"type":112,"value":697},"Cache reason",{"type":112,"value":425},{"type":106,"tag":171,"props":700,"children":702},{"className":701},[],[703],{"type":112,"value":54},{"type":112,"value":705},") — the finer ",{"type":106,"tag":138,"props":707,"children":708},{},[709],{"type":112,"value":710},"explanation",{"type":112,"value":712}," of that outcome for a single request. The ",{"type":106,"tag":171,"props":714,"children":716},{"className":715},[],[717],{"type":112,"value":718},"cache_result",{"type":112,"value":720}," metric lumps all ",{"type":106,"tag":171,"props":722,"children":724},{"className":723},[],[725],{"type":112,"value":346},{"type":112,"value":727},"es (and all ",{"type":106,"tag":171,"props":729,"children":731},{"className":730},[],[732],{"type":112,"value":331},{"type":112,"value":734},"s) together; the reason is the only thing that tells them apart. Nine values, three per group:",{"type":106,"tag":543,"props":736,"children":737},{},[738,761],{"type":106,"tag":547,"props":739,"children":740},{},[741],{"type":106,"tag":551,"props":742,"children":743},{},[744,752,757],{"type":106,"tag":555,"props":745,"children":746},{},[747],{"type":106,"tag":171,"props":748,"children":750},{"className":749},[],[751],{"type":112,"value":54},{"type":106,"tag":555,"props":753,"children":754},{},[755],{"type":112,"value":756},"Refines",{"type":106,"tag":555,"props":758,"children":759},{},[760],{"type":112,"value":564},{"type":106,"tag":566,"props":762,"children":763},{},[764,785,805,826,847,867,887,914,948],{"type":106,"tag":551,"props":765,"children":766},{},[767,776,780],{"type":106,"tag":573,"props":768,"children":769},{},[770],{"type":106,"tag":171,"props":771,"children":773},{"className":772},[],[774],{"type":112,"value":775},"cold",{"type":106,"tag":573,"props":777,"children":778},{},[779],{"type":112,"value":346},{"type":106,"tag":573,"props":781,"children":782},{},[783],{"type":112,"value":784},"Cache empty for this key\u002Fvariant (first request or evicted); the function ran",{"type":106,"tag":551,"props":786,"children":787},{},[788,796,800],{"type":106,"tag":573,"props":789,"children":790},{},[791],{"type":106,"tag":171,"props":792,"children":794},{"className":793},[],[795],{"type":112,"value":96},{"type":106,"tag":573,"props":797,"children":798},{},[799],{"type":112,"value":346},{"type":106,"tag":573,"props":801,"children":802},{},[803],{"type":112,"value":804},"Concurrent requests to one uncached path collapsed into a single invocation",{"type":106,"tag":551,"props":806,"children":807},{},[808,817,821],{"type":106,"tag":573,"props":809,"children":810},{},[811],{"type":106,"tag":171,"props":812,"children":814},{"className":813},[],[815],{"type":112,"value":816},"error",{"type":106,"tag":573,"props":818,"children":819},{},[820],{"type":112,"value":346},{"type":106,"tag":573,"props":822,"children":823},{},[824],{"type":112,"value":825},"An error prevented serving from cache",{"type":106,"tag":551,"props":827,"children":828},{},[829,837,842],{"type":106,"tag":573,"props":830,"children":831},{},[832],{"type":106,"tag":171,"props":833,"children":835},{"className":834},[],[836],{"type":112,"value":62},{"type":106,"tag":573,"props":838,"children":839},{},[840],{"type":112,"value":841},"→ BYPASS",{"type":106,"tag":573,"props":843,"children":844},{},[845],{"type":112,"value":846},"Next.js Draft Mode active — bypassed so editors see live content",{"type":106,"tag":551,"props":848,"children":849},{},[850,858,862],{"type":106,"tag":573,"props":851,"children":852},{},[853],{"type":106,"tag":171,"props":854,"children":856},{"className":855},[],[857],{"type":112,"value":63},{"type":106,"tag":573,"props":859,"children":860},{},[861],{"type":112,"value":841},{"type":106,"tag":573,"props":863,"children":864},{},[865],{"type":112,"value":866},"Prerender-bypass cookie\u002Ftoken present",{"type":106,"tag":551,"props":868,"children":869},{},[870,878,882],{"type":106,"tag":573,"props":871,"children":872},{},[873],{"type":106,"tag":171,"props":874,"children":876},{"className":875},[],[877],{"type":112,"value":86},{"type":106,"tag":573,"props":879,"children":880},{},[881],{"type":112,"value":841},{"type":106,"tag":573,"props":883,"children":884},{},[885],{"type":112,"value":886},"SEO-crawler UA — full response served so bots index real content",{"type":106,"tag":551,"props":888,"children":889},{},[890,898,902],{"type":106,"tag":573,"props":891,"children":892},{},[893],{"type":106,"tag":171,"props":894,"children":896},{"className":895},[],[897],{"type":112,"value":59},{"type":106,"tag":573,"props":899,"children":900},{},[901],{"type":112,"value":331},{"type":106,"tag":573,"props":903,"children":904},{},[905,907,912],{"type":112,"value":906},"Time-based ",{"type":106,"tag":171,"props":908,"children":910},{"className":909},[],[911],{"type":112,"value":82},{"type":112,"value":913}," interval elapsed; regenerating in background (SWR)",{"type":106,"tag":551,"props":915,"children":916},{},[917,925,929],{"type":106,"tag":573,"props":918,"children":919},{},[920],{"type":106,"tag":171,"props":921,"children":923},{"className":922},[],[924],{"type":112,"value":60},{"type":106,"tag":573,"props":926,"children":927},{},[928],{"type":112,"value":331},{"type":106,"tag":573,"props":930,"children":931},{},[932,934,939,941,946],{"type":112,"value":933},"Tag invalidated (",{"type":106,"tag":171,"props":935,"children":937},{"className":936},[],[938],{"type":112,"value":439},{"type":112,"value":940}," \u002F ",{"type":106,"tag":171,"props":942,"children":944},{"className":943},[],[945],{"type":112,"value":431},{"type":112,"value":947},"); regenerating",{"type":106,"tag":551,"props":949,"children":950},{},[951,959,963],{"type":106,"tag":573,"props":952,"children":953},{},[954],{"type":106,"tag":171,"props":955,"children":957},{"className":956},[],[958],{"type":112,"value":61},{"type":106,"tag":573,"props":960,"children":961},{},[962],{"type":112,"value":331},{"type":106,"tag":573,"props":964,"children":965},{},[966,968,973],{"type":112,"value":967},"A revalidation attempt ",{"type":106,"tag":149,"props":969,"children":970},{},[971],{"type":112,"value":972},"failed",{"type":112,"value":974},"; serving the last-good copy (a bug signal)",{"type":106,"tag":976,"props":977,"children":978},"br",{},[],{"type":112,"value":980},"A raw ",{"type":106,"tag":171,"props":982,"children":984},{"className":983},[],[985],{"type":112,"value":346},{"type":112,"value":987}," with reason ",{"type":106,"tag":171,"props":989,"children":991},{"className":990},[],[992],{"type":112,"value":62},{"type":112,"value":940},{"type":106,"tag":171,"props":995,"children":997},{"className":996},[],[998],{"type":112,"value":63},{"type":112,"value":940},{"type":106,"tag":171,"props":1001,"children":1003},{"className":1002},[],[1004],{"type":112,"value":86},{"type":112,"value":1006}," is ",{"type":106,"tag":149,"props":1008,"children":1009},{},[1010,1012],{"type":112,"value":1011},"displayed as ",{"type":106,"tag":171,"props":1013,"children":1015},{"className":1014},[],[1016],{"type":112,"value":368},{"type":112,"value":1018}," (all usually expected). The three ",{"type":106,"tag":171,"props":1020,"children":1022},{"className":1021},[],[1023],{"type":112,"value":1024},"stale_*",{"type":112,"value":1026}," reasons separate a healthy time refresh (",{"type":106,"tag":171,"props":1028,"children":1030},{"className":1029},[],[1031],{"type":112,"value":59},{"type":112,"value":1033},") from a broad-tag blast (",{"type":106,"tag":171,"props":1035,"children":1037},{"className":1036},[],[1038],{"type":112,"value":60},{"type":112,"value":1040},") from a failing regen (",{"type":106,"tag":171,"props":1042,"children":1044},{"className":1043},[],[1045],{"type":112,"value":61},{"type":112,"value":1047},"). Read ",{"type":106,"tag":171,"props":1049,"children":1051},{"className":1050},[],[1052],{"type":112,"value":54},{"type":112,"value":1054}," from ",{"type":106,"tag":171,"props":1056,"children":1058},{"className":1057},[],[1059],{"type":112,"value":1060},"vercel logs",{"type":112,"value":1062}," or the dashboard Logs \"Reason\" row — the ",{"type":106,"tag":171,"props":1064,"children":1066},{"className":1065},[],[1067],{"type":112,"value":55},{"type":112,"value":1069}," header is internal-only and not visible via ",{"type":106,"tag":171,"props":1071,"children":1073},{"className":1072},[],[1074],{"type":112,"value":1075},"curl",{"type":112,"value":230},{"type":106,"tag":132,"props":1078,"children":1079},{},[1080,1085,1086,1091,1093,1098,1100,1106,1108,1113,1114,1120,1121,1127,1129,1134,1136,1231,1234,1236,1241,1243,1247,1249,1254,1255,1260,1262,1268,1270,1275,1277,1282,1283,1288],{"type":106,"tag":149,"props":1081,"children":1082},{},[1083],{"type":112,"value":1084},"PPR state",{"type":112,"value":425},{"type":106,"tag":171,"props":1087,"children":1089},{"className":1088},[],[1090],{"type":112,"value":57},{"type":112,"value":1092},") — for a Partial Prerendering route, ",{"type":106,"tag":138,"props":1094,"children":1095},{},[1096],{"type":112,"value":1097},"how much",{"type":112,"value":1099}," of the response was prerendered versus computed per request. Only set on ",{"type":106,"tag":171,"props":1101,"children":1103},{"className":1102},[],[1104],{"type":112,"value":1105},"partial_prerender",{"type":112,"value":1107}," serves; blank for plain ",{"type":106,"tag":171,"props":1109,"children":1111},{"className":1110},[],[1112],{"type":112,"value":83},{"type":112,"value":940},{"type":106,"tag":171,"props":1115,"children":1117},{"className":1116},[],[1118],{"type":112,"value":1119},"func",{"type":112,"value":940},{"type":106,"tag":171,"props":1122,"children":1124},{"className":1123},[],[1125],{"type":112,"value":1126},"static",{"type":112,"value":1128}," routes and for cases the proxy can't classify (cold shell miss, ",{"type":106,"tag":171,"props":1130,"children":1132},{"className":1131},[],[1133],{"type":112,"value":368},{"type":112,"value":1135},"). Three values:",{"type":106,"tag":543,"props":1137,"children":1138},{},[1139,1162],{"type":106,"tag":547,"props":1140,"children":1141},{},[1142],{"type":106,"tag":551,"props":1143,"children":1144},{},[1145,1153,1158],{"type":106,"tag":555,"props":1146,"children":1147},{},[1148],{"type":106,"tag":171,"props":1149,"children":1151},{"className":1150},[],[1152],{"type":112,"value":57},{"type":106,"tag":555,"props":1154,"children":1155},{},[1156],{"type":112,"value":1157},"Shown as",{"type":106,"tag":555,"props":1159,"children":1160},{},[1161],{"type":112,"value":564},{"type":106,"tag":566,"props":1163,"children":1164},{},[1165,1187,1209],{"type":106,"tag":551,"props":1166,"children":1167},{},[1168,1177,1182],{"type":106,"tag":573,"props":1169,"children":1170},{},[1171],{"type":106,"tag":171,"props":1172,"children":1174},{"className":1173},[],[1175],{"type":112,"value":1176},"page",{"type":106,"tag":573,"props":1178,"children":1179},{},[1180],{"type":112,"value":1181},"Static",{"type":106,"tag":573,"props":1183,"children":1184},{},[1185],{"type":112,"value":1186},"Fully prerendered — no postponed state, so the function is not invoked for the body",{"type":106,"tag":551,"props":1188,"children":1189},{},[1190,1199,1204],{"type":106,"tag":573,"props":1191,"children":1192},{},[1193],{"type":106,"tag":171,"props":1194,"children":1196},{"className":1195},[],[1197],{"type":112,"value":1198},"shell",{"type":106,"tag":573,"props":1200,"children":1201},{},[1202],{"type":112,"value":1203},"Partial",{"type":106,"tag":573,"props":1205,"children":1206},{},[1207],{"type":112,"value":1208},"Non-empty static shell from cache + a postponed hole the function resumes per request",{"type":106,"tag":551,"props":1210,"children":1211},{},[1212,1221,1226],{"type":106,"tag":573,"props":1213,"children":1214},{},[1215],{"type":106,"tag":171,"props":1216,"children":1218},{"className":1217},[],[1219],{"type":112,"value":1220},"blocking",{"type":106,"tag":573,"props":1222,"children":1223},{},[1224],{"type":112,"value":1225},"Dynamic",{"type":106,"tag":573,"props":1227,"children":1228},{},[1229],{"type":112,"value":1230},"Empty shell — the whole body is postponed and rendered by the function per request",{"type":106,"tag":976,"props":1232,"children":1233},{},[],{"type":112,"value":1235},"A shell hit that still invokes the function is ",{"type":106,"tag":171,"props":1237,"children":1239},{"className":1238},[],[1240],{"type":112,"value":1198},{"type":112,"value":1242}," (Partial), ",{"type":106,"tag":138,"props":1244,"children":1245},{},[1246],{"type":112,"value":160},{"type":112,"value":1248}," a cache miss — the cached shell serves immediately while the function fills only the dynamic holes. Read ",{"type":106,"tag":171,"props":1250,"children":1252},{"className":1251},[],[1253],{"type":112,"value":57},{"type":112,"value":1054},{"type":106,"tag":171,"props":1256,"children":1258},{"className":1257},[],[1259],{"type":112,"value":1060},{"type":112,"value":1261}," or the dashboard Logs panel, or aggregate with ",{"type":106,"tag":171,"props":1263,"children":1265},{"className":1264},[],[1266],{"type":112,"value":1267},"vercel metrics vercel.request.count --group-by ppr_state",{"type":112,"value":1269},". Like ",{"type":106,"tag":171,"props":1271,"children":1273},{"className":1272},[],[1274],{"type":112,"value":54},{"type":112,"value":1276},", the ",{"type":106,"tag":171,"props":1278,"children":1280},{"className":1279},[],[1281],{"type":112,"value":58},{"type":112,"value":1069},{"type":106,"tag":171,"props":1284,"children":1286},{"className":1285},[],[1287],{"type":112,"value":1075},{"type":112,"value":230},{"type":106,"tag":121,"props":1290,"children":1292},{"id":1291},"investigating-cache-issues",[1293],{"type":112,"value":1294},"Investigating cache issues",{"type":106,"tag":115,"props":1296,"children":1297},{},[1298,1300,1306,1308,1315,1317,1322],{"type":112,"value":1299},"Reach for the Vercel CLI. ",{"type":106,"tag":171,"props":1301,"children":1303},{"className":1302},[],[1304],{"type":112,"value":1305},"vercel metrics",{"type":112,"value":1307}," gives aggregate numbers (requires ",{"type":106,"tag":241,"props":1309,"children":1312},{"href":1310,"rel":1311},"https:\u002F\u002Fvercel.com\u002Fdocs\u002Fobservability\u002Fobservability-plus",[245],[1313],{"type":112,"value":1314},"Observability Plus",{"type":112,"value":1316},"); ",{"type":106,"tag":171,"props":1318,"children":1320},{"className":1319},[],[1321],{"type":112,"value":1060},{"type":112,"value":1323}," shows per-request behavior.",{"type":106,"tag":115,"props":1325,"children":1326},{},[1327,1329,1335,1337,1343,1345,1351,1353,1359,1361,1367,1369,1375,1377,1388,1390,1395],{"type":112,"value":1328},"Metrics need to be queried by team and project (",{"type":106,"tag":171,"props":1330,"children":1332},{"className":1331},[],[1333],{"type":112,"value":1334},"-S \u003Cteam> -p \u003Cproject>",{"type":112,"value":1336},"). Filter production with ",{"type":106,"tag":171,"props":1338,"children":1340},{"className":1339},[],[1341],{"type":112,"value":1342},"-f \"environment eq 'production'\"",{"type":112,"value":1344}," (there is no ",{"type":106,"tag":171,"props":1346,"children":1348},{"className":1347},[],[1349],{"type":112,"value":1350},"--prod",{"type":112,"value":1352}," flag). Run ",{"type":106,"tag":171,"props":1354,"children":1356},{"className":1355},[],[1357],{"type":112,"value":1358},"vercel metrics schema \u003Cmetric>",{"type":112,"value":1360}," to discover dimensions; use ",{"type":106,"tag":171,"props":1362,"children":1364},{"className":1363},[],[1365],{"type":112,"value":1366},"-F json",{"type":112,"value":1368}," for machine-readable output. With ",{"type":106,"tag":171,"props":1370,"children":1372},{"className":1371},[],[1373],{"type":112,"value":1374},"-g",{"type":112,"value":1376},", remember ",{"type":106,"tag":149,"props":1378,"children":1379},{},[1380,1386],{"type":106,"tag":171,"props":1381,"children":1383},{"className":1382},[],[1384],{"type":112,"value":1385},"--limit",{"type":112,"value":1387}," is per time bucket",{"type":112,"value":1389}," — omit ",{"type":106,"tag":171,"props":1391,"children":1393},{"className":1392},[],[1394],{"type":112,"value":1374},{"type":112,"value":1396}," when you need totals across the whole window.",{"type":106,"tag":179,"props":1398,"children":1400},{"id":1399},"cache-hit-rate",[1401],{"type":112,"value":315},{"type":106,"tag":115,"props":1403,"children":1404},{},[1405],{"type":112,"value":1406},"Start here for an overall picture of how well caching is working.",{"type":106,"tag":115,"props":1408,"children":1409},{},[1410,1415,1417,1423,1425,1430,1432,1437,1438,1443,1445,1450,1452,1457,1459,1464,1465,1470,1472,1476,1478,1484,1486,1491,1493,1499],{"type":106,"tag":149,"props":1411,"children":1412},{},[1413],{"type":112,"value":1414},"Step 1 — overall split.",{"type":112,"value":1416}," Group ",{"type":106,"tag":171,"props":1418,"children":1420},{"className":1419},[],[1421],{"type":112,"value":1422},"vercel.request.count",{"type":112,"value":1424}," by ",{"type":106,"tag":171,"props":1426,"children":1428},{"className":1427},[],[1429],{"type":112,"value":718},{"type":112,"value":1431},". Treat ",{"type":106,"tag":171,"props":1433,"children":1435},{"className":1434},[],[1436],{"type":112,"value":323},{"type":112,"value":681},{"type":106,"tag":171,"props":1439,"children":1441},{"className":1440},[],[1442],{"type":112,"value":331},{"type":112,"value":1444},", and ",{"type":106,"tag":171,"props":1446,"children":1448},{"className":1447},[],[1449],{"type":112,"value":338},{"type":112,"value":1451}," as cache-served; focus investigation on ",{"type":106,"tag":171,"props":1453,"children":1455},{"className":1454},[],[1456],{"type":112,"value":346},{"type":112,"value":1458},". Exclude ",{"type":106,"tag":171,"props":1460,"children":1462},{"className":1461},[],[1463],{"type":112,"value":368},{"type":112,"value":370},{"type":106,"tag":171,"props":1466,"children":1468},{"className":1467},[],[1469],{"type":112,"value":376},{"type":112,"value":1471}," when computing a hit rate over ",{"type":106,"tag":138,"props":1473,"children":1474},{},[1475],{"type":112,"value":360},{"type":112,"value":1477}," traffic (see ",{"type":106,"tag":241,"props":1479,"children":1481},{"href":1480},"#debugging-bypass-traffic",[1482],{"type":112,"value":1483},"Debugging BYPASS traffic",{"type":112,"value":1485},"). ",{"type":106,"tag":171,"props":1487,"children":1489},{"className":1488},[],[1490],{"type":112,"value":331},{"type":112,"value":1492}," means stale-while-revalidate is working — dig into revalidation frequency in ",{"type":106,"tag":241,"props":1494,"children":1496},{"href":1495},"#analyzing-isr-costs",[1497],{"type":112,"value":1498},"Analyzing ISR costs",{"type":112,"value":1500},", not here.",{"type":106,"tag":1502,"props":1503,"children":1508},"pre",{"className":1504,"code":1505,"language":1506,"meta":1507,"style":1507},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","vercel metrics vercel.request.count -S \u003Cteam> -p \u003Cproject> \\\n  -f \"environment eq 'production'\" --group-by cache_result --since 24h\n","bash","",[1509],{"type":106,"tag":171,"props":1510,"children":1511},{"__ignoreMap":1507},[1512,1589],{"type":106,"tag":1513,"props":1514,"children":1517},"span",{"class":1515,"line":1516},"line",1,[1518,1523,1529,1534,1539,1545,1550,1556,1561,1566,1570,1575,1580,1584],{"type":106,"tag":1513,"props":1519,"children":1521},{"style":1520},"--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B",[1522],{"type":112,"value":8},{"type":106,"tag":1513,"props":1524,"children":1526},{"style":1525},"--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D",[1527],{"type":112,"value":1528}," metrics",{"type":106,"tag":1513,"props":1530,"children":1531},{"style":1525},[1532],{"type":112,"value":1533}," vercel.request.count",{"type":106,"tag":1513,"props":1535,"children":1536},{"style":1525},[1537],{"type":112,"value":1538}," -S",{"type":106,"tag":1513,"props":1540,"children":1542},{"style":1541},"--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF",[1543],{"type":112,"value":1544}," \u003C",{"type":106,"tag":1513,"props":1546,"children":1547},{"style":1525},[1548],{"type":112,"value":1549},"tea",{"type":106,"tag":1513,"props":1551,"children":1553},{"style":1552},"--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8",[1554],{"type":112,"value":1555},"m",{"type":106,"tag":1513,"props":1557,"children":1558},{"style":1541},[1559],{"type":112,"value":1560},">",{"type":106,"tag":1513,"props":1562,"children":1563},{"style":1525},[1564],{"type":112,"value":1565}," -p",{"type":106,"tag":1513,"props":1567,"children":1568},{"style":1541},[1569],{"type":112,"value":1544},{"type":106,"tag":1513,"props":1571,"children":1572},{"style":1525},[1573],{"type":112,"value":1574},"projec",{"type":106,"tag":1513,"props":1576,"children":1577},{"style":1552},[1578],{"type":112,"value":1579},"t",{"type":106,"tag":1513,"props":1581,"children":1582},{"style":1541},[1583],{"type":112,"value":1560},{"type":106,"tag":1513,"props":1585,"children":1586},{"style":1552},[1587],{"type":112,"value":1588}," \\\n",{"type":106,"tag":1513,"props":1590,"children":1592},{"class":1515,"line":1591},2,[1593,1598,1603,1608,1613,1618,1623,1628],{"type":106,"tag":1513,"props":1594,"children":1595},{"style":1525},[1596],{"type":112,"value":1597},"  -f",{"type":106,"tag":1513,"props":1599,"children":1600},{"style":1541},[1601],{"type":112,"value":1602}," \"",{"type":106,"tag":1513,"props":1604,"children":1605},{"style":1525},[1606],{"type":112,"value":1607},"environment eq 'production'",{"type":106,"tag":1513,"props":1609,"children":1610},{"style":1541},[1611],{"type":112,"value":1612},"\"",{"type":106,"tag":1513,"props":1614,"children":1615},{"style":1525},[1616],{"type":112,"value":1617}," --group-by",{"type":106,"tag":1513,"props":1619,"children":1620},{"style":1525},[1621],{"type":112,"value":1622}," cache_result",{"type":106,"tag":1513,"props":1624,"children":1625},{"style":1525},[1626],{"type":112,"value":1627}," --since",{"type":106,"tag":1513,"props":1629,"children":1630},{"style":1525},[1631],{"type":112,"value":1632}," 24h\n",{"type":106,"tag":115,"props":1634,"children":1635},{},[1636,1641,1643,1648,1650,1655,1657,1663,1665,1671,1673,1679],{"type":106,"tag":149,"props":1637,"children":1638},{},[1639],{"type":112,"value":1640},"Step 2 — where misses concentrate.",{"type":112,"value":1642}," Split the ",{"type":106,"tag":171,"props":1644,"children":1646},{"className":1645},[],[1647],{"type":112,"value":346},{"type":112,"value":1649}," bucket (and optionally ",{"type":106,"tag":171,"props":1651,"children":1653},{"className":1652},[],[1654],{"type":112,"value":331},{"type":112,"value":1656},") by ",{"type":106,"tag":171,"props":1658,"children":1660},{"className":1659},[],[1661],{"type":112,"value":1662},"path_type",{"type":112,"value":1664},", then by ",{"type":106,"tag":171,"props":1666,"children":1668},{"className":1667},[],[1669],{"type":112,"value":1670},"route",{"type":112,"value":1672}," or ",{"type":106,"tag":171,"props":1674,"children":1676},{"className":1675},[],[1677],{"type":112,"value":1678},"request_path",{"type":112,"value":541},{"type":106,"tag":1502,"props":1681,"children":1683},{"className":1504,"code":1682,"language":1506,"meta":1507,"style":1507},"vercel metrics vercel.request.count -S \u003Cteam> -p \u003Cproject> \\\n  -f \"environment eq 'production' and cache_result eq 'MISS'\" \\\n  --group-by path_type --since 24h\n\nvercel metrics vercel.request.count -S \u003Cteam> -p \u003Cproject> \\\n  -f \"environment eq 'production' and cache_result eq 'MISS' and path_type eq 'prerender'\" \\\n  --group-by request_path --since 24h\n",[1684],{"type":106,"tag":171,"props":1685,"children":1686},{"__ignoreMap":1507},[1687,1746,1770,1792,1802,1862,1886],{"type":106,"tag":1513,"props":1688,"children":1689},{"class":1515,"line":1516},[1690,1694,1698,1702,1706,1710,1714,1718,1722,1726,1730,1734,1738,1742],{"type":106,"tag":1513,"props":1691,"children":1692},{"style":1520},[1693],{"type":112,"value":8},{"type":106,"tag":1513,"props":1695,"children":1696},{"style":1525},[1697],{"type":112,"value":1528},{"type":106,"tag":1513,"props":1699,"children":1700},{"style":1525},[1701],{"type":112,"value":1533},{"type":106,"tag":1513,"props":1703,"children":1704},{"style":1525},[1705],{"type":112,"value":1538},{"type":106,"tag":1513,"props":1707,"children":1708},{"style":1541},[1709],{"type":112,"value":1544},{"type":106,"tag":1513,"props":1711,"children":1712},{"style":1525},[1713],{"type":112,"value":1549},{"type":106,"tag":1513,"props":1715,"children":1716},{"style":1552},[1717],{"type":112,"value":1555},{"type":106,"tag":1513,"props":1719,"children":1720},{"style":1541},[1721],{"type":112,"value":1560},{"type":106,"tag":1513,"props":1723,"children":1724},{"style":1525},[1725],{"type":112,"value":1565},{"type":106,"tag":1513,"props":1727,"children":1728},{"style":1541},[1729],{"type":112,"value":1544},{"type":106,"tag":1513,"props":1731,"children":1732},{"style":1525},[1733],{"type":112,"value":1574},{"type":106,"tag":1513,"props":1735,"children":1736},{"style":1552},[1737],{"type":112,"value":1579},{"type":106,"tag":1513,"props":1739,"children":1740},{"style":1541},[1741],{"type":112,"value":1560},{"type":106,"tag":1513,"props":1743,"children":1744},{"style":1552},[1745],{"type":112,"value":1588},{"type":106,"tag":1513,"props":1747,"children":1748},{"class":1515,"line":1591},[1749,1753,1757,1762,1766],{"type":106,"tag":1513,"props":1750,"children":1751},{"style":1525},[1752],{"type":112,"value":1597},{"type":106,"tag":1513,"props":1754,"children":1755},{"style":1541},[1756],{"type":112,"value":1602},{"type":106,"tag":1513,"props":1758,"children":1759},{"style":1525},[1760],{"type":112,"value":1761},"environment eq 'production' and cache_result eq 'MISS'",{"type":106,"tag":1513,"props":1763,"children":1764},{"style":1541},[1765],{"type":112,"value":1612},{"type":106,"tag":1513,"props":1767,"children":1768},{"style":1552},[1769],{"type":112,"value":1588},{"type":106,"tag":1513,"props":1771,"children":1773},{"class":1515,"line":1772},3,[1774,1779,1784,1788],{"type":106,"tag":1513,"props":1775,"children":1776},{"style":1525},[1777],{"type":112,"value":1778},"  --group-by",{"type":106,"tag":1513,"props":1780,"children":1781},{"style":1525},[1782],{"type":112,"value":1783}," path_type",{"type":106,"tag":1513,"props":1785,"children":1786},{"style":1525},[1787],{"type":112,"value":1627},{"type":106,"tag":1513,"props":1789,"children":1790},{"style":1525},[1791],{"type":112,"value":1632},{"type":106,"tag":1513,"props":1793,"children":1795},{"class":1515,"line":1794},4,[1796],{"type":106,"tag":1513,"props":1797,"children":1799},{"emptyLinePlaceholder":1798},true,[1800],{"type":112,"value":1801},"\n",{"type":106,"tag":1513,"props":1803,"children":1805},{"class":1515,"line":1804},5,[1806,1810,1814,1818,1822,1826,1830,1834,1838,1842,1846,1850,1854,1858],{"type":106,"tag":1513,"props":1807,"children":1808},{"style":1520},[1809],{"type":112,"value":8},{"type":106,"tag":1513,"props":1811,"children":1812},{"style":1525},[1813],{"type":112,"value":1528},{"type":106,"tag":1513,"props":1815,"children":1816},{"style":1525},[1817],{"type":112,"value":1533},{"type":106,"tag":1513,"props":1819,"children":1820},{"style":1525},[1821],{"type":112,"value":1538},{"type":106,"tag":1513,"props":1823,"children":1824},{"style":1541},[1825],{"type":112,"value":1544},{"type":106,"tag":1513,"props":1827,"children":1828},{"style":1525},[1829],{"type":112,"value":1549},{"type":106,"tag":1513,"props":1831,"children":1832},{"style":1552},[1833],{"type":112,"value":1555},{"type":106,"tag":1513,"props":1835,"children":1836},{"style":1541},[1837],{"type":112,"value":1560},{"type":106,"tag":1513,"props":1839,"children":1840},{"style":1525},[1841],{"type":112,"value":1565},{"type":106,"tag":1513,"props":1843,"children":1844},{"style":1541},[1845],{"type":112,"value":1544},{"type":106,"tag":1513,"props":1847,"children":1848},{"style":1525},[1849],{"type":112,"value":1574},{"type":106,"tag":1513,"props":1851,"children":1852},{"style":1552},[1853],{"type":112,"value":1579},{"type":106,"tag":1513,"props":1855,"children":1856},{"style":1541},[1857],{"type":112,"value":1560},{"type":106,"tag":1513,"props":1859,"children":1860},{"style":1552},[1861],{"type":112,"value":1588},{"type":106,"tag":1513,"props":1863,"children":1864},{"class":1515,"line":37},[1865,1869,1873,1878,1882],{"type":106,"tag":1513,"props":1866,"children":1867},{"style":1525},[1868],{"type":112,"value":1597},{"type":106,"tag":1513,"props":1870,"children":1871},{"style":1541},[1872],{"type":112,"value":1602},{"type":106,"tag":1513,"props":1874,"children":1875},{"style":1525},[1876],{"type":112,"value":1877},"environment eq 'production' and cache_result eq 'MISS' and path_type eq 'prerender'",{"type":106,"tag":1513,"props":1879,"children":1880},{"style":1541},[1881],{"type":112,"value":1612},{"type":106,"tag":1513,"props":1883,"children":1884},{"style":1552},[1885],{"type":112,"value":1588},{"type":106,"tag":1513,"props":1887,"children":1889},{"class":1515,"line":1888},7,[1890,1894,1899,1903],{"type":106,"tag":1513,"props":1891,"children":1892},{"style":1525},[1893],{"type":112,"value":1778},{"type":106,"tag":1513,"props":1895,"children":1896},{"style":1525},[1897],{"type":112,"value":1898}," request_path",{"type":106,"tag":1513,"props":1900,"children":1901},{"style":1525},[1902],{"type":112,"value":1627},{"type":106,"tag":1513,"props":1904,"children":1905},{"style":1525},[1906],{"type":112,"value":1632},{"type":106,"tag":115,"props":1908,"children":1909},{},[1910,1915,1917,1922,1924,1929,1930,1935,1937,1942,1944,1949,1951,1956],{"type":106,"tag":149,"props":1911,"children":1912},{},[1913],{"type":112,"value":1914},"What to expect:",{"type":112,"value":1916}," ",{"type":106,"tag":171,"props":1918,"children":1920},{"className":1919},[],[1921],{"type":112,"value":83},{"type":112,"value":1923}," routes (static shells, ISR pages) should show a high share of ",{"type":106,"tag":171,"props":1925,"children":1927},{"className":1926},[],[1928],{"type":112,"value":323},{"type":112,"value":325},{"type":106,"tag":171,"props":1931,"children":1933},{"className":1932},[],[1934],{"type":112,"value":338},{"type":112,"value":1936},". A ",{"type":106,"tag":171,"props":1938,"children":1940},{"className":1939},[],[1941],{"type":112,"value":83},{"type":112,"value":1943}," path with a disproportionate ",{"type":106,"tag":171,"props":1945,"children":1947},{"className":1946},[],[1948],{"type":112,"value":346},{"type":112,"value":1950}," count is your short list for per-path header inspection (",{"type":106,"tag":171,"props":1952,"children":1954},{"className":1953},[],[1955],{"type":112,"value":1075},{"type":112,"value":1957}," above) and code review.",{"type":106,"tag":115,"props":1959,"children":1960},{},[1961,1967,1969,1975,1977,1983,1985,1990],{"type":106,"tag":171,"props":1962,"children":1964},{"className":1963},[],[1965],{"type":112,"value":1966},"streaming_func",{"type":112,"value":1968}," routes render dynamically by default, but you can still cache them with ",{"type":106,"tag":171,"props":1970,"children":1972},{"className":1971},[],[1973],{"type":112,"value":1974},"Cache-Control",{"type":112,"value":1976}," headers — matching requests are cached on the CDN. Each cache entry varies by ",{"type":106,"tag":171,"props":1978,"children":1980},{"className":1979},[],[1981],{"type":112,"value":1982},"Vary",{"type":112,"value":1984}," headers (cookies, RSC, etc.) as well as path and query parameters, so expect more cache keys and a lower hit rate than a fully static ",{"type":106,"tag":171,"props":1986,"children":1988},{"className":1987},[],[1989],{"type":112,"value":83},{"type":112,"value":1991}," route.",{"type":106,"tag":179,"props":1993,"children":1995},{"id":1994},"analyzing-isr-costs",[1996],{"type":112,"value":1498},{"type":106,"tag":115,"props":1998,"children":1999},{},[2000],{"type":112,"value":2001},"Once you know hit rate, quantify ISR spend and whether revalidation — not traffic volume — is driving it.",{"type":106,"tag":115,"props":2003,"children":2004},{},[2005,2010,2011,2016,2017,2022,2024,2029,2031,2037,2039,2045,2047,2052,2054,2058],{"type":106,"tag":149,"props":2006,"children":2007},{},[2008],{"type":112,"value":2009},"Utilization vs. ISR billing.",{"type":112,"value":1916},{"type":106,"tag":149,"props":2012,"children":2013},{},[2014],{"type":112,"value":2015},"Utilization",{"type":112,"value":1006},{"type":106,"tag":171,"props":2018,"children":2020},{"className":2019},[],[2021],{"type":112,"value":1422},{"type":112,"value":2023}," — total request volume. ",{"type":106,"tag":149,"props":2025,"children":2026},{},[2027],{"type":112,"value":2028},"ISR cost",{"type":112,"value":2030}," is billed separately in 8 KB units: ",{"type":106,"tag":171,"props":2032,"children":2034},{"className":2033},[],[2035],{"type":112,"value":2036},"read_units",{"type":112,"value":2038}," when the regional CDN misses and falls through to the ISR cache, and ",{"type":106,"tag":171,"props":2040,"children":2042},{"className":2041},[],[2043],{"type":112,"value":2044},"write_units",{"type":112,"value":2046}," on every revalidation\u002Fregeneration. The regional CDN shields ISR heavily — most requests never touch the ISR layer, so ",{"type":106,"tag":149,"props":2048,"children":2049},{},[2050],{"type":112,"value":2051},"read_units will be far below request count",{"type":112,"value":2053},". Do not compare read_units to write_units as a utilization check; focus on ",{"type":106,"tag":149,"props":2055,"children":2056},{},[2057],{"type":112,"value":2044},{"type":112,"value":2059}," (revalidation cost) and how they relate to total traffic.",{"type":106,"tag":1502,"props":2061,"children":2063},{"className":1504,"code":2062,"language":1506,"meta":1507,"style":1507},"vercel metrics vercel.request.count -S \u003Cteam> -p \u003Cproject> -a sum --since 24h\nvercel metrics vercel.isr_operation.write_units -S \u003Cteam> -p \u003Cproject> -a sum --since 24h\n",[2064],{"type":106,"tag":171,"props":2065,"children":2066},{"__ignoreMap":1507},[2067,2140],{"type":106,"tag":1513,"props":2068,"children":2069},{"class":1515,"line":1516},[2070,2074,2078,2082,2086,2090,2094,2098,2102,2106,2110,2114,2118,2122,2127,2132,2136],{"type":106,"tag":1513,"props":2071,"children":2072},{"style":1520},[2073],{"type":112,"value":8},{"type":106,"tag":1513,"props":2075,"children":2076},{"style":1525},[2077],{"type":112,"value":1528},{"type":106,"tag":1513,"props":2079,"children":2080},{"style":1525},[2081],{"type":112,"value":1533},{"type":106,"tag":1513,"props":2083,"children":2084},{"style":1525},[2085],{"type":112,"value":1538},{"type":106,"tag":1513,"props":2087,"children":2088},{"style":1541},[2089],{"type":112,"value":1544},{"type":106,"tag":1513,"props":2091,"children":2092},{"style":1525},[2093],{"type":112,"value":1549},{"type":106,"tag":1513,"props":2095,"children":2096},{"style":1552},[2097],{"type":112,"value":1555},{"type":106,"tag":1513,"props":2099,"children":2100},{"style":1541},[2101],{"type":112,"value":1560},{"type":106,"tag":1513,"props":2103,"children":2104},{"style":1525},[2105],{"type":112,"value":1565},{"type":106,"tag":1513,"props":2107,"children":2108},{"style":1541},[2109],{"type":112,"value":1544},{"type":106,"tag":1513,"props":2111,"children":2112},{"style":1525},[2113],{"type":112,"value":1574},{"type":106,"tag":1513,"props":2115,"children":2116},{"style":1552},[2117],{"type":112,"value":1579},{"type":106,"tag":1513,"props":2119,"children":2120},{"style":1541},[2121],{"type":112,"value":1560},{"type":106,"tag":1513,"props":2123,"children":2124},{"style":1525},[2125],{"type":112,"value":2126}," -a",{"type":106,"tag":1513,"props":2128,"children":2129},{"style":1525},[2130],{"type":112,"value":2131}," sum",{"type":106,"tag":1513,"props":2133,"children":2134},{"style":1525},[2135],{"type":112,"value":1627},{"type":106,"tag":1513,"props":2137,"children":2138},{"style":1525},[2139],{"type":112,"value":1632},{"type":106,"tag":1513,"props":2141,"children":2142},{"class":1515,"line":1591},[2143,2147,2151,2156,2160,2164,2168,2172,2176,2180,2184,2188,2192,2196,2200,2204,2208],{"type":106,"tag":1513,"props":2144,"children":2145},{"style":1520},[2146],{"type":112,"value":8},{"type":106,"tag":1513,"props":2148,"children":2149},{"style":1525},[2150],{"type":112,"value":1528},{"type":106,"tag":1513,"props":2152,"children":2153},{"style":1525},[2154],{"type":112,"value":2155}," vercel.isr_operation.write_units",{"type":106,"tag":1513,"props":2157,"children":2158},{"style":1525},[2159],{"type":112,"value":1538},{"type":106,"tag":1513,"props":2161,"children":2162},{"style":1541},[2163],{"type":112,"value":1544},{"type":106,"tag":1513,"props":2165,"children":2166},{"style":1525},[2167],{"type":112,"value":1549},{"type":106,"tag":1513,"props":2169,"children":2170},{"style":1552},[2171],{"type":112,"value":1555},{"type":106,"tag":1513,"props":2173,"children":2174},{"style":1541},[2175],{"type":112,"value":1560},{"type":106,"tag":1513,"props":2177,"children":2178},{"style":1525},[2179],{"type":112,"value":1565},{"type":106,"tag":1513,"props":2181,"children":2182},{"style":1541},[2183],{"type":112,"value":1544},{"type":106,"tag":1513,"props":2185,"children":2186},{"style":1525},[2187],{"type":112,"value":1574},{"type":106,"tag":1513,"props":2189,"children":2190},{"style":1552},[2191],{"type":112,"value":1579},{"type":106,"tag":1513,"props":2193,"children":2194},{"style":1541},[2195],{"type":112,"value":1560},{"type":106,"tag":1513,"props":2197,"children":2198},{"style":1525},[2199],{"type":112,"value":2126},{"type":106,"tag":1513,"props":2201,"children":2202},{"style":1525},[2203],{"type":112,"value":2131},{"type":106,"tag":1513,"props":2205,"children":2206},{"style":1525},[2207],{"type":112,"value":1627},{"type":106,"tag":1513,"props":2209,"children":2210},{"style":1525},[2211],{"type":112,"value":1632},{"type":106,"tag":115,"props":2213,"children":2214},{},[2215,2220],{"type":106,"tag":149,"props":2216,"children":2217},{},[2218],{"type":112,"value":2219},"Write utilization = cache serves ÷ ISR writes",{"type":112,"value":2221}," — cached reads per regeneration.",{"type":106,"tag":1502,"props":2223,"children":2225},{"className":1504,"code":2224,"language":1506,"meta":1507,"style":1507},"# numerator: cache serves — sum the HIT + STALE + PRERENDER buckets\nvercel metrics vercel.request.count -S \u003Cteam> -p \u003Cproject> \\\n  -f \"environment eq 'production' and (cache_result eq 'HIT' or cache_result eq 'STALE')\" \\\n  --group-by route -a sum --since 24h\n# denominator: ISR writes\nvercel metrics vercel.isr_operation.write_units -S \u003Cteam> -p \u003Cproject> \\\n  -f \"environment eq 'production'\" --group-by route -a sum --since 24h\n",[2226],{"type":106,"tag":171,"props":2227,"children":2228},{"__ignoreMap":1507},[2229,2238,2297,2321,2349,2357,2416],{"type":106,"tag":1513,"props":2230,"children":2231},{"class":1515,"line":1516},[2232],{"type":106,"tag":1513,"props":2233,"children":2235},{"style":2234},"--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic",[2236],{"type":112,"value":2237},"# numerator: cache serves — sum the HIT + STALE + PRERENDER buckets\n",{"type":106,"tag":1513,"props":2239,"children":2240},{"class":1515,"line":1591},[2241,2245,2249,2253,2257,2261,2265,2269,2273,2277,2281,2285,2289,2293],{"type":106,"tag":1513,"props":2242,"children":2243},{"style":1520},[2244],{"type":112,"value":8},{"type":106,"tag":1513,"props":2246,"children":2247},{"style":1525},[2248],{"type":112,"value":1528},{"type":106,"tag":1513,"props":2250,"children":2251},{"style":1525},[2252],{"type":112,"value":1533},{"type":106,"tag":1513,"props":2254,"children":2255},{"style":1525},[2256],{"type":112,"value":1538},{"type":106,"tag":1513,"props":2258,"children":2259},{"style":1541},[2260],{"type":112,"value":1544},{"type":106,"tag":1513,"props":2262,"children":2263},{"style":1525},[2264],{"type":112,"value":1549},{"type":106,"tag":1513,"props":2266,"children":2267},{"style":1552},[2268],{"type":112,"value":1555},{"type":106,"tag":1513,"props":2270,"children":2271},{"style":1541},[2272],{"type":112,"value":1560},{"type":106,"tag":1513,"props":2274,"children":2275},{"style":1525},[2276],{"type":112,"value":1565},{"type":106,"tag":1513,"props":2278,"children":2279},{"style":1541},[2280],{"type":112,"value":1544},{"type":106,"tag":1513,"props":2282,"children":2283},{"style":1525},[2284],{"type":112,"value":1574},{"type":106,"tag":1513,"props":2286,"children":2287},{"style":1552},[2288],{"type":112,"value":1579},{"type":106,"tag":1513,"props":2290,"children":2291},{"style":1541},[2292],{"type":112,"value":1560},{"type":106,"tag":1513,"props":2294,"children":2295},{"style":1552},[2296],{"type":112,"value":1588},{"type":106,"tag":1513,"props":2298,"children":2299},{"class":1515,"line":1772},[2300,2304,2308,2313,2317],{"type":106,"tag":1513,"props":2301,"children":2302},{"style":1525},[2303],{"type":112,"value":1597},{"type":106,"tag":1513,"props":2305,"children":2306},{"style":1541},[2307],{"type":112,"value":1602},{"type":106,"tag":1513,"props":2309,"children":2310},{"style":1525},[2311],{"type":112,"value":2312},"environment eq 'production' and (cache_result eq 'HIT' or cache_result eq 'STALE')",{"type":106,"tag":1513,"props":2314,"children":2315},{"style":1541},[2316],{"type":112,"value":1612},{"type":106,"tag":1513,"props":2318,"children":2319},{"style":1552},[2320],{"type":112,"value":1588},{"type":106,"tag":1513,"props":2322,"children":2323},{"class":1515,"line":1794},[2324,2328,2333,2337,2341,2345],{"type":106,"tag":1513,"props":2325,"children":2326},{"style":1525},[2327],{"type":112,"value":1778},{"type":106,"tag":1513,"props":2329,"children":2330},{"style":1525},[2331],{"type":112,"value":2332}," route",{"type":106,"tag":1513,"props":2334,"children":2335},{"style":1525},[2336],{"type":112,"value":2126},{"type":106,"tag":1513,"props":2338,"children":2339},{"style":1525},[2340],{"type":112,"value":2131},{"type":106,"tag":1513,"props":2342,"children":2343},{"style":1525},[2344],{"type":112,"value":1627},{"type":106,"tag":1513,"props":2346,"children":2347},{"style":1525},[2348],{"type":112,"value":1632},{"type":106,"tag":1513,"props":2350,"children":2351},{"class":1515,"line":1804},[2352],{"type":106,"tag":1513,"props":2353,"children":2354},{"style":2234},[2355],{"type":112,"value":2356},"# denominator: ISR writes\n",{"type":106,"tag":1513,"props":2358,"children":2359},{"class":1515,"line":37},[2360,2364,2368,2372,2376,2380,2384,2388,2392,2396,2400,2404,2408,2412],{"type":106,"tag":1513,"props":2361,"children":2362},{"style":1520},[2363],{"type":112,"value":8},{"type":106,"tag":1513,"props":2365,"children":2366},{"style":1525},[2367],{"type":112,"value":1528},{"type":106,"tag":1513,"props":2369,"children":2370},{"style":1525},[2371],{"type":112,"value":2155},{"type":106,"tag":1513,"props":2373,"children":2374},{"style":1525},[2375],{"type":112,"value":1538},{"type":106,"tag":1513,"props":2377,"children":2378},{"style":1541},[2379],{"type":112,"value":1544},{"type":106,"tag":1513,"props":2381,"children":2382},{"style":1525},[2383],{"type":112,"value":1549},{"type":106,"tag":1513,"props":2385,"children":2386},{"style":1552},[2387],{"type":112,"value":1555},{"type":106,"tag":1513,"props":2389,"children":2390},{"style":1541},[2391],{"type":112,"value":1560},{"type":106,"tag":1513,"props":2393,"children":2394},{"style":1525},[2395],{"type":112,"value":1565},{"type":106,"tag":1513,"props":2397,"children":2398},{"style":1541},[2399],{"type":112,"value":1544},{"type":106,"tag":1513,"props":2401,"children":2402},{"style":1525},[2403],{"type":112,"value":1574},{"type":106,"tag":1513,"props":2405,"children":2406},{"style":1552},[2407],{"type":112,"value":1579},{"type":106,"tag":1513,"props":2409,"children":2410},{"style":1541},[2411],{"type":112,"value":1560},{"type":106,"tag":1513,"props":2413,"children":2414},{"style":1552},[2415],{"type":112,"value":1588},{"type":106,"tag":1513,"props":2417,"children":2418},{"class":1515,"line":1888},[2419,2423,2427,2431,2435,2439,2443,2447,2451,2455],{"type":106,"tag":1513,"props":2420,"children":2421},{"style":1525},[2422],{"type":112,"value":1597},{"type":106,"tag":1513,"props":2424,"children":2425},{"style":1541},[2426],{"type":112,"value":1602},{"type":106,"tag":1513,"props":2428,"children":2429},{"style":1525},[2430],{"type":112,"value":1607},{"type":106,"tag":1513,"props":2432,"children":2433},{"style":1541},[2434],{"type":112,"value":1612},{"type":106,"tag":1513,"props":2436,"children":2437},{"style":1525},[2438],{"type":112,"value":1617},{"type":106,"tag":1513,"props":2440,"children":2441},{"style":1525},[2442],{"type":112,"value":2332},{"type":106,"tag":1513,"props":2444,"children":2445},{"style":1525},[2446],{"type":112,"value":2126},{"type":106,"tag":1513,"props":2448,"children":2449},{"style":1525},[2450],{"type":112,"value":2131},{"type":106,"tag":1513,"props":2452,"children":2453},{"style":1525},[2454],{"type":112,"value":1627},{"type":106,"tag":1513,"props":2456,"children":2457},{"style":1525},[2458],{"type":112,"value":1632},{"type":106,"tag":115,"props":2460,"children":2461},{},[2462],{"type":112,"value":2463},"High is good; near or below ~1 means you regenerate about as fast as the page is read (wasted writes) → lengthen the revalidate interval or move time-based to on-demand tag revalidation.",{"type":106,"tag":115,"props":2465,"children":2466},{},[2467,2472,2474,2479,2480,2485],{"type":106,"tag":149,"props":2468,"children":2469},{},[2470],{"type":112,"value":2471},"Which routes revalidate most.",{"type":112,"value":2473}," Break write units down by ",{"type":106,"tag":171,"props":2475,"children":2477},{"className":2476},[],[2478],{"type":112,"value":1670},{"type":112,"value":370},{"type":106,"tag":171,"props":2481,"children":2483},{"className":2482},[],[2484],{"type":112,"value":1678},{"type":112,"value":2486}," to find paths that regenerate often relative to traffic:",{"type":106,"tag":1502,"props":2488,"children":2490},{"className":1504,"code":2489,"language":1506,"meta":1507,"style":1507},"vercel metrics vercel.isr_operation.write_units -S \u003Cteam> -p \u003Cproject> \\\n  -a sum --group-by route --since 24h\n\nvercel metrics vercel.isr_operation.write_units -S \u003Cteam> -p \u003Cproject> \\\n  -a sum --group-by request_path --since 24h\n",[2491],{"type":106,"tag":171,"props":2492,"children":2493},{"__ignoreMap":1507},[2494,2553,2581,2588,2647],{"type":106,"tag":1513,"props":2495,"children":2496},{"class":1515,"line":1516},[2497,2501,2505,2509,2513,2517,2521,2525,2529,2533,2537,2541,2545,2549],{"type":106,"tag":1513,"props":2498,"children":2499},{"style":1520},[2500],{"type":112,"value":8},{"type":106,"tag":1513,"props":2502,"children":2503},{"style":1525},[2504],{"type":112,"value":1528},{"type":106,"tag":1513,"props":2506,"children":2507},{"style":1525},[2508],{"type":112,"value":2155},{"type":106,"tag":1513,"props":2510,"children":2511},{"style":1525},[2512],{"type":112,"value":1538},{"type":106,"tag":1513,"props":2514,"children":2515},{"style":1541},[2516],{"type":112,"value":1544},{"type":106,"tag":1513,"props":2518,"children":2519},{"style":1525},[2520],{"type":112,"value":1549},{"type":106,"tag":1513,"props":2522,"children":2523},{"style":1552},[2524],{"type":112,"value":1555},{"type":106,"tag":1513,"props":2526,"children":2527},{"style":1541},[2528],{"type":112,"value":1560},{"type":106,"tag":1513,"props":2530,"children":2531},{"style":1525},[2532],{"type":112,"value":1565},{"type":106,"tag":1513,"props":2534,"children":2535},{"style":1541},[2536],{"type":112,"value":1544},{"type":106,"tag":1513,"props":2538,"children":2539},{"style":1525},[2540],{"type":112,"value":1574},{"type":106,"tag":1513,"props":2542,"children":2543},{"style":1552},[2544],{"type":112,"value":1579},{"type":106,"tag":1513,"props":2546,"children":2547},{"style":1541},[2548],{"type":112,"value":1560},{"type":106,"tag":1513,"props":2550,"children":2551},{"style":1552},[2552],{"type":112,"value":1588},{"type":106,"tag":1513,"props":2554,"children":2555},{"class":1515,"line":1591},[2556,2561,2565,2569,2573,2577],{"type":106,"tag":1513,"props":2557,"children":2558},{"style":1525},[2559],{"type":112,"value":2560},"  -a",{"type":106,"tag":1513,"props":2562,"children":2563},{"style":1525},[2564],{"type":112,"value":2131},{"type":106,"tag":1513,"props":2566,"children":2567},{"style":1525},[2568],{"type":112,"value":1617},{"type":106,"tag":1513,"props":2570,"children":2571},{"style":1525},[2572],{"type":112,"value":2332},{"type":106,"tag":1513,"props":2574,"children":2575},{"style":1525},[2576],{"type":112,"value":1627},{"type":106,"tag":1513,"props":2578,"children":2579},{"style":1525},[2580],{"type":112,"value":1632},{"type":106,"tag":1513,"props":2582,"children":2583},{"class":1515,"line":1772},[2584],{"type":106,"tag":1513,"props":2585,"children":2586},{"emptyLinePlaceholder":1798},[2587],{"type":112,"value":1801},{"type":106,"tag":1513,"props":2589,"children":2590},{"class":1515,"line":1794},[2591,2595,2599,2603,2607,2611,2615,2619,2623,2627,2631,2635,2639,2643],{"type":106,"tag":1513,"props":2592,"children":2593},{"style":1520},[2594],{"type":112,"value":8},{"type":106,"tag":1513,"props":2596,"children":2597},{"style":1525},[2598],{"type":112,"value":1528},{"type":106,"tag":1513,"props":2600,"children":2601},{"style":1525},[2602],{"type":112,"value":2155},{"type":106,"tag":1513,"props":2604,"children":2605},{"style":1525},[2606],{"type":112,"value":1538},{"type":106,"tag":1513,"props":2608,"children":2609},{"style":1541},[2610],{"type":112,"value":1544},{"type":106,"tag":1513,"props":2612,"children":2613},{"style":1525},[2614],{"type":112,"value":1549},{"type":106,"tag":1513,"props":2616,"children":2617},{"style":1552},[2618],{"type":112,"value":1555},{"type":106,"tag":1513,"props":2620,"children":2621},{"style":1541},[2622],{"type":112,"value":1560},{"type":106,"tag":1513,"props":2624,"children":2625},{"style":1525},[2626],{"type":112,"value":1565},{"type":106,"tag":1513,"props":2628,"children":2629},{"style":1541},[2630],{"type":112,"value":1544},{"type":106,"tag":1513,"props":2632,"children":2633},{"style":1525},[2634],{"type":112,"value":1574},{"type":106,"tag":1513,"props":2636,"children":2637},{"style":1552},[2638],{"type":112,"value":1579},{"type":106,"tag":1513,"props":2640,"children":2641},{"style":1541},[2642],{"type":112,"value":1560},{"type":106,"tag":1513,"props":2644,"children":2645},{"style":1552},[2646],{"type":112,"value":1588},{"type":106,"tag":1513,"props":2648,"children":2649},{"class":1515,"line":1804},[2650,2654,2658,2662,2666,2670],{"type":106,"tag":1513,"props":2651,"children":2652},{"style":1525},[2653],{"type":112,"value":2560},{"type":106,"tag":1513,"props":2655,"children":2656},{"style":1525},[2657],{"type":112,"value":2131},{"type":106,"tag":1513,"props":2659,"children":2660},{"style":1525},[2661],{"type":112,"value":1617},{"type":106,"tag":1513,"props":2663,"children":2664},{"style":1525},[2665],{"type":112,"value":1898},{"type":106,"tag":1513,"props":2667,"children":2668},{"style":1525},[2669],{"type":112,"value":1627},{"type":106,"tag":1513,"props":2671,"children":2672},{"style":1525},[2673],{"type":112,"value":1632},{"type":106,"tag":115,"props":2675,"children":2676},{},[2677,2682,2684,2689,2691,2697],{"type":106,"tag":149,"props":2678,"children":2679},{},[2680],{"type":112,"value":2681},"Regeneration vs. serving.",{"type":112,"value":2683}," Group write units by ",{"type":106,"tag":171,"props":2685,"children":2687},{"className":2686},[],[2688],{"type":112,"value":1662},{"type":112,"value":2690}," — concentration in ",{"type":106,"tag":171,"props":2692,"children":2694},{"className":2693},[],[2695],{"type":112,"value":2696},"background_func",{"type":112,"value":2698}," confirms revalidation (not per-request dynamic work) is the cost driver.",{"type":106,"tag":115,"props":2700,"children":2701},{},[2702,2707,2709,2714],{"type":106,"tag":149,"props":2703,"children":2704},{},[2705],{"type":112,"value":2706},"Time-based vs. tag-based revalidation.",{"type":112,"value":2708}," Time-based intervals regenerate on a schedule whether or not content changed — often inefficient. Tag-based on-demand revalidation is usually better, but an ",{"type":106,"tag":149,"props":2710,"children":2711},{},[2712],{"type":112,"value":2713},"overly broad tag",{"type":112,"value":2715}," has a large blast radius: one invalidate drops every entry that carries it.",{"type":106,"tag":128,"props":2717,"children":2718},{},[2719],{"type":106,"tag":132,"props":2720,"children":2721},{},[2722,2727,2729,2735,2737,2742,2744,2750],{"type":106,"tag":149,"props":2723,"children":2724},{},[2725],{"type":112,"value":2726},"Tag blast radius",{"type":112,"value":2728}," — group write units by ",{"type":106,"tag":171,"props":2730,"children":2732},{"className":2731},[],[2733],{"type":112,"value":2734},"cache_tags",{"type":112,"value":2736},". If many ",{"type":106,"tag":138,"props":2738,"children":2739},{},[2740],{"type":112,"value":2741},"unrelated",{"type":112,"value":2743}," routes show near-identical write counts, a shared hot tag is invalidating them in lockstep (e.g. every blog post rewriting at the same rate because they share one broad ",{"type":106,"tag":171,"props":2745,"children":2747},{"className":2746},[],[2748],{"type":112,"value":2749},"blogPost",{"type":112,"value":2751}," tag):",{"type":106,"tag":1502,"props":2753,"children":2755},{"className":1504,"code":2754,"language":1506,"meta":1507,"style":1507},"vercel metrics vercel.isr_operation.write_units -S \u003Cteam> -p \u003Cproject> \\\n  -a sum --group-by cache_tags --since 24h\n",[2756],{"type":106,"tag":171,"props":2757,"children":2758},{"__ignoreMap":1507},[2759,2818],{"type":106,"tag":1513,"props":2760,"children":2761},{"class":1515,"line":1516},[2762,2766,2770,2774,2778,2782,2786,2790,2794,2798,2802,2806,2810,2814],{"type":106,"tag":1513,"props":2763,"children":2764},{"style":1520},[2765],{"type":112,"value":8},{"type":106,"tag":1513,"props":2767,"children":2768},{"style":1525},[2769],{"type":112,"value":1528},{"type":106,"tag":1513,"props":2771,"children":2772},{"style":1525},[2773],{"type":112,"value":2155},{"type":106,"tag":1513,"props":2775,"children":2776},{"style":1525},[2777],{"type":112,"value":1538},{"type":106,"tag":1513,"props":2779,"children":2780},{"style":1541},[2781],{"type":112,"value":1544},{"type":106,"tag":1513,"props":2783,"children":2784},{"style":1525},[2785],{"type":112,"value":1549},{"type":106,"tag":1513,"props":2787,"children":2788},{"style":1552},[2789],{"type":112,"value":1555},{"type":106,"tag":1513,"props":2791,"children":2792},{"style":1541},[2793],{"type":112,"value":1560},{"type":106,"tag":1513,"props":2795,"children":2796},{"style":1525},[2797],{"type":112,"value":1565},{"type":106,"tag":1513,"props":2799,"children":2800},{"style":1541},[2801],{"type":112,"value":1544},{"type":106,"tag":1513,"props":2803,"children":2804},{"style":1525},[2805],{"type":112,"value":1574},{"type":106,"tag":1513,"props":2807,"children":2808},{"style":1552},[2809],{"type":112,"value":1579},{"type":106,"tag":1513,"props":2811,"children":2812},{"style":1541},[2813],{"type":112,"value":1560},{"type":106,"tag":1513,"props":2815,"children":2816},{"style":1552},[2817],{"type":112,"value":1588},{"type":106,"tag":1513,"props":2819,"children":2820},{"class":1515,"line":1591},[2821,2825,2829,2833,2838,2842],{"type":106,"tag":1513,"props":2822,"children":2823},{"style":1525},[2824],{"type":112,"value":2560},{"type":106,"tag":1513,"props":2826,"children":2827},{"style":1525},[2828],{"type":112,"value":2131},{"type":106,"tag":1513,"props":2830,"children":2831},{"style":1525},[2832],{"type":112,"value":1617},{"type":106,"tag":1513,"props":2834,"children":2835},{"style":1525},[2836],{"type":112,"value":2837}," cache_tags",{"type":106,"tag":1513,"props":2839,"children":2840},{"style":1525},[2841],{"type":112,"value":1627},{"type":106,"tag":1513,"props":2843,"children":2844},{"style":1525},[2845],{"type":112,"value":1632},{"type":106,"tag":128,"props":2847,"children":2848},{},[2849],{"type":106,"tag":132,"props":2850,"children":2851},{},[2852,2857,2859,2864,2865,2871,2873,2878],{"type":106,"tag":149,"props":2853,"children":2854},{},[2855],{"type":112,"value":2856},"What triggered revalidation",{"type":112,"value":2858}," — group ",{"type":106,"tag":171,"props":2860,"children":2862},{"className":2861},[],[2863],{"type":112,"value":1422},{"type":112,"value":1424},{"type":106,"tag":171,"props":2866,"children":2868},{"className":2867},[],[2869],{"type":112,"value":2870},"triggering_tag",{"type":112,"value":2872}," to see which tags fire most often (",{"type":106,"tag":171,"props":2874,"children":2876},{"className":2875},[],[2877],{"type":112,"value":2870},{"type":112,"value":2879}," is on request count only, not ISR operation metrics. It is one of the tags that triggered the page to be stale):",{"type":106,"tag":1502,"props":2881,"children":2883},{"className":1504,"code":2882,"language":1506,"meta":1507,"style":1507},"vercel metrics vercel.request.count -S \u003Cteam> -p \u003Cproject> \\\n  -f \"triggering_tag ne null\" --group-by triggering_tag --since 24h\n",[2884],{"type":106,"tag":171,"props":2885,"children":2886},{"__ignoreMap":1507},[2887,2946],{"type":106,"tag":1513,"props":2888,"children":2889},{"class":1515,"line":1516},[2890,2894,2898,2902,2906,2910,2914,2918,2922,2926,2930,2934,2938,2942],{"type":106,"tag":1513,"props":2891,"children":2892},{"style":1520},[2893],{"type":112,"value":8},{"type":106,"tag":1513,"props":2895,"children":2896},{"style":1525},[2897],{"type":112,"value":1528},{"type":106,"tag":1513,"props":2899,"children":2900},{"style":1525},[2901],{"type":112,"value":1533},{"type":106,"tag":1513,"props":2903,"children":2904},{"style":1525},[2905],{"type":112,"value":1538},{"type":106,"tag":1513,"props":2907,"children":2908},{"style":1541},[2909],{"type":112,"value":1544},{"type":106,"tag":1513,"props":2911,"children":2912},{"style":1525},[2913],{"type":112,"value":1549},{"type":106,"tag":1513,"props":2915,"children":2916},{"style":1552},[2917],{"type":112,"value":1555},{"type":106,"tag":1513,"props":2919,"children":2920},{"style":1541},[2921],{"type":112,"value":1560},{"type":106,"tag":1513,"props":2923,"children":2924},{"style":1525},[2925],{"type":112,"value":1565},{"type":106,"tag":1513,"props":2927,"children":2928},{"style":1541},[2929],{"type":112,"value":1544},{"type":106,"tag":1513,"props":2931,"children":2932},{"style":1525},[2933],{"type":112,"value":1574},{"type":106,"tag":1513,"props":2935,"children":2936},{"style":1552},[2937],{"type":112,"value":1579},{"type":106,"tag":1513,"props":2939,"children":2940},{"style":1541},[2941],{"type":112,"value":1560},{"type":106,"tag":1513,"props":2943,"children":2944},{"style":1552},[2945],{"type":112,"value":1588},{"type":106,"tag":1513,"props":2947,"children":2948},{"class":1515,"line":1591},[2949,2953,2957,2962,2966,2970,2975,2979],{"type":106,"tag":1513,"props":2950,"children":2951},{"style":1525},[2952],{"type":112,"value":1597},{"type":106,"tag":1513,"props":2954,"children":2955},{"style":1541},[2956],{"type":112,"value":1602},{"type":106,"tag":1513,"props":2958,"children":2959},{"style":1525},[2960],{"type":112,"value":2961},"triggering_tag ne null",{"type":106,"tag":1513,"props":2963,"children":2964},{"style":1541},[2965],{"type":112,"value":1612},{"type":106,"tag":1513,"props":2967,"children":2968},{"style":1525},[2969],{"type":112,"value":1617},{"type":106,"tag":1513,"props":2971,"children":2972},{"style":1525},[2973],{"type":112,"value":2974}," triggering_tag",{"type":106,"tag":1513,"props":2976,"children":2977},{"style":1525},[2978],{"type":112,"value":1627},{"type":106,"tag":1513,"props":2980,"children":2981},{"style":1525},[2982],{"type":112,"value":1632},{"type":106,"tag":115,"props":2984,"children":2985},{},[2986,2988,2993],{"type":112,"value":2987},"Tags with a large blast radius that revalidate frequently are the usual root cause of high write_units. Prefer granular tags (",{"type":106,"tag":171,"props":2989,"children":2991},{"className":2990},[],[2992],{"type":112,"value":516},{"type":112,"value":2994},") and on-demand invalidation over short time-based intervals for event-driven content.",{"type":106,"tag":115,"props":2996,"children":2997},{},[2998,3003,3005,3010,3012,3016,3018,3024,3025,3031,3032,3038,3039,3045,3047,3052,3054,3060],{"type":106,"tag":149,"props":2999,"children":3000},{},[3001],{"type":112,"value":3002},"Confirm in code.",{"type":112,"value":3004}," Metrics tell you ",{"type":106,"tag":138,"props":3006,"children":3007},{},[3008],{"type":112,"value":3009},"which",{"type":112,"value":3011}," tag is hot; the repo tells you ",{"type":106,"tag":138,"props":3013,"children":3014},{},[3015],{"type":112,"value":76},{"type":112,"value":3017},". Grep for the tag's invalidation call site — ",{"type":106,"tag":171,"props":3019,"children":3021},{"className":3020},[],[3022],{"type":112,"value":3023},"revalidateTag(",{"type":112,"value":681},{"type":106,"tag":171,"props":3026,"children":3028},{"className":3027},[],[3029],{"type":112,"value":3030},"invalidateByTag(",{"type":112,"value":681},{"type":106,"tag":171,"props":3033,"children":3035},{"className":3034},[],[3036],{"type":112,"value":3037},"updateTag(",{"type":112,"value":681},{"type":106,"tag":171,"props":3040,"children":3042},{"className":3041},[],[3043],{"type":112,"value":3044},"dangerouslyDeleteByTag(",{"type":112,"value":3046}," — and read the trigger. A CMS webhook or a sync cron that invalidates a ",{"type":106,"tag":149,"props":3048,"children":3049},{},[3050],{"type":112,"value":3051},"broad",{"type":112,"value":3053}," tag on every event (instead of a specific ",{"type":106,"tag":171,"props":3055,"children":3057},{"className":3056},[],[3058],{"type":112,"value":3059},"${type}:${id}",{"type":112,"value":3061},") is the classic amplifier.",{"type":106,"tag":179,"props":3063,"children":3065},{"id":3064},"debugging-bypass-traffic",[3066],{"type":112,"value":1483},{"type":106,"tag":115,"props":3068,"children":3069},{},[3070,3072,3077,3079,3084,3085,3090,3092,3097],{"type":112,"value":3071},"The largest legitimate sources of ",{"type":106,"tag":171,"props":3073,"children":3075},{"className":3074},[],[3076],{"type":112,"value":368},{"type":112,"value":3078}," are ",{"type":106,"tag":149,"props":3080,"children":3081},{},[3082],{"type":112,"value":3083},"Draft Mode",{"type":112,"value":370},{"type":106,"tag":149,"props":3086,"children":3087},{},[3088],{"type":112,"value":3089},"SEO crawlers",{"type":112,"value":3091},". Draft Mode must bypass cache so editors see live content. SEO bots must receive the ",{"type":106,"tag":149,"props":3093,"children":3094},{},[3095],{"type":112,"value":3096},"full response",{"type":112,"value":3098}," — especially on PPR routes where the static shell and dynamic holes are assembled at request time — so crawlers index what users actually see. That BYPASS is expected, not a misconfiguration.",{"type":106,"tag":115,"props":3100,"children":3101},{},[3102],{"type":112,"value":3103},"Before tuning headers or revalidate intervals, confirm what's left after those two buckets:",{"type":106,"tag":1502,"props":3105,"children":3107},{"className":1504,"code":3106,"language":1506,"meta":1507,"style":1507},"vercel metrics vercel.request.count -S \u003Cteam> -p \u003Cproject> \\\n  -f \"cache_result eq 'BYPASS'\" --group-by bot_category --since 24h\n\nvercel metrics vercel.request.count -S \u003Cteam> -p \u003Cproject> \\\n  -f \"cache_result eq 'BYPASS'\" --group-by user_agent --since 24h\n\nvercel metrics vercel.request.count -S \u003Cteam> -p \u003Cproject> \\\n  -f \"cache_result eq 'BYPASS'\" --group-by request_method --since 24h\n",[3108],{"type":106,"tag":171,"props":3109,"children":3110},{"__ignoreMap":1507},[3111,3170,3207,3214,3273,3309,3316,3375],{"type":106,"tag":1513,"props":3112,"children":3113},{"class":1515,"line":1516},[3114,3118,3122,3126,3130,3134,3138,3142,3146,3150,3154,3158,3162,3166],{"type":106,"tag":1513,"props":3115,"children":3116},{"style":1520},[3117],{"type":112,"value":8},{"type":106,"tag":1513,"props":3119,"children":3120},{"style":1525},[3121],{"type":112,"value":1528},{"type":106,"tag":1513,"props":3123,"children":3124},{"style":1525},[3125],{"type":112,"value":1533},{"type":106,"tag":1513,"props":3127,"children":3128},{"style":1525},[3129],{"type":112,"value":1538},{"type":106,"tag":1513,"props":3131,"children":3132},{"style":1541},[3133],{"type":112,"value":1544},{"type":106,"tag":1513,"props":3135,"children":3136},{"style":1525},[3137],{"type":112,"value":1549},{"type":106,"tag":1513,"props":3139,"children":3140},{"style":1552},[3141],{"type":112,"value":1555},{"type":106,"tag":1513,"props":3143,"children":3144},{"style":1541},[3145],{"type":112,"value":1560},{"type":106,"tag":1513,"props":3147,"children":3148},{"style":1525},[3149],{"type":112,"value":1565},{"type":106,"tag":1513,"props":3151,"children":3152},{"style":1541},[3153],{"type":112,"value":1544},{"type":106,"tag":1513,"props":3155,"children":3156},{"style":1525},[3157],{"type":112,"value":1574},{"type":106,"tag":1513,"props":3159,"children":3160},{"style":1552},[3161],{"type":112,"value":1579},{"type":106,"tag":1513,"props":3163,"children":3164},{"style":1541},[3165],{"type":112,"value":1560},{"type":106,"tag":1513,"props":3167,"children":3168},{"style":1552},[3169],{"type":112,"value":1588},{"type":106,"tag":1513,"props":3171,"children":3172},{"class":1515,"line":1591},[3173,3177,3181,3186,3190,3194,3199,3203],{"type":106,"tag":1513,"props":3174,"children":3175},{"style":1525},[3176],{"type":112,"value":1597},{"type":106,"tag":1513,"props":3178,"children":3179},{"style":1541},[3180],{"type":112,"value":1602},{"type":106,"tag":1513,"props":3182,"children":3183},{"style":1525},[3184],{"type":112,"value":3185},"cache_result eq 'BYPASS'",{"type":106,"tag":1513,"props":3187,"children":3188},{"style":1541},[3189],{"type":112,"value":1612},{"type":106,"tag":1513,"props":3191,"children":3192},{"style":1525},[3193],{"type":112,"value":1617},{"type":106,"tag":1513,"props":3195,"children":3196},{"style":1525},[3197],{"type":112,"value":3198}," bot_category",{"type":106,"tag":1513,"props":3200,"children":3201},{"style":1525},[3202],{"type":112,"value":1627},{"type":106,"tag":1513,"props":3204,"children":3205},{"style":1525},[3206],{"type":112,"value":1632},{"type":106,"tag":1513,"props":3208,"children":3209},{"class":1515,"line":1772},[3210],{"type":106,"tag":1513,"props":3211,"children":3212},{"emptyLinePlaceholder":1798},[3213],{"type":112,"value":1801},{"type":106,"tag":1513,"props":3215,"children":3216},{"class":1515,"line":1794},[3217,3221,3225,3229,3233,3237,3241,3245,3249,3253,3257,3261,3265,3269],{"type":106,"tag":1513,"props":3218,"children":3219},{"style":1520},[3220],{"type":112,"value":8},{"type":106,"tag":1513,"props":3222,"children":3223},{"style":1525},[3224],{"type":112,"value":1528},{"type":106,"tag":1513,"props":3226,"children":3227},{"style":1525},[3228],{"type":112,"value":1533},{"type":106,"tag":1513,"props":3230,"children":3231},{"style":1525},[3232],{"type":112,"value":1538},{"type":106,"tag":1513,"props":3234,"children":3235},{"style":1541},[3236],{"type":112,"value":1544},{"type":106,"tag":1513,"props":3238,"children":3239},{"style":1525},[3240],{"type":112,"value":1549},{"type":106,"tag":1513,"props":3242,"children":3243},{"style":1552},[3244],{"type":112,"value":1555},{"type":106,"tag":1513,"props":3246,"children":3247},{"style":1541},[3248],{"type":112,"value":1560},{"type":106,"tag":1513,"props":3250,"children":3251},{"style":1525},[3252],{"type":112,"value":1565},{"type":106,"tag":1513,"props":3254,"children":3255},{"style":1541},[3256],{"type":112,"value":1544},{"type":106,"tag":1513,"props":3258,"children":3259},{"style":1525},[3260],{"type":112,"value":1574},{"type":106,"tag":1513,"props":3262,"children":3263},{"style":1552},[3264],{"type":112,"value":1579},{"type":106,"tag":1513,"props":3266,"children":3267},{"style":1541},[3268],{"type":112,"value":1560},{"type":106,"tag":1513,"props":3270,"children":3271},{"style":1552},[3272],{"type":112,"value":1588},{"type":106,"tag":1513,"props":3274,"children":3275},{"class":1515,"line":1804},[3276,3280,3284,3288,3292,3296,3301,3305],{"type":106,"tag":1513,"props":3277,"children":3278},{"style":1525},[3279],{"type":112,"value":1597},{"type":106,"tag":1513,"props":3281,"children":3282},{"style":1541},[3283],{"type":112,"value":1602},{"type":106,"tag":1513,"props":3285,"children":3286},{"style":1525},[3287],{"type":112,"value":3185},{"type":106,"tag":1513,"props":3289,"children":3290},{"style":1541},[3291],{"type":112,"value":1612},{"type":106,"tag":1513,"props":3293,"children":3294},{"style":1525},[3295],{"type":112,"value":1617},{"type":106,"tag":1513,"props":3297,"children":3298},{"style":1525},[3299],{"type":112,"value":3300}," user_agent",{"type":106,"tag":1513,"props":3302,"children":3303},{"style":1525},[3304],{"type":112,"value":1627},{"type":106,"tag":1513,"props":3306,"children":3307},{"style":1525},[3308],{"type":112,"value":1632},{"type":106,"tag":1513,"props":3310,"children":3311},{"class":1515,"line":37},[3312],{"type":106,"tag":1513,"props":3313,"children":3314},{"emptyLinePlaceholder":1798},[3315],{"type":112,"value":1801},{"type":106,"tag":1513,"props":3317,"children":3318},{"class":1515,"line":1888},[3319,3323,3327,3331,3335,3339,3343,3347,3351,3355,3359,3363,3367,3371],{"type":106,"tag":1513,"props":3320,"children":3321},{"style":1520},[3322],{"type":112,"value":8},{"type":106,"tag":1513,"props":3324,"children":3325},{"style":1525},[3326],{"type":112,"value":1528},{"type":106,"tag":1513,"props":3328,"children":3329},{"style":1525},[3330],{"type":112,"value":1533},{"type":106,"tag":1513,"props":3332,"children":3333},{"style":1525},[3334],{"type":112,"value":1538},{"type":106,"tag":1513,"props":3336,"children":3337},{"style":1541},[3338],{"type":112,"value":1544},{"type":106,"tag":1513,"props":3340,"children":3341},{"style":1525},[3342],{"type":112,"value":1549},{"type":106,"tag":1513,"props":3344,"children":3345},{"style":1552},[3346],{"type":112,"value":1555},{"type":106,"tag":1513,"props":3348,"children":3349},{"style":1541},[3350],{"type":112,"value":1560},{"type":106,"tag":1513,"props":3352,"children":3353},{"style":1525},[3354],{"type":112,"value":1565},{"type":106,"tag":1513,"props":3356,"children":3357},{"style":1541},[3358],{"type":112,"value":1544},{"type":106,"tag":1513,"props":3360,"children":3361},{"style":1525},[3362],{"type":112,"value":1574},{"type":106,"tag":1513,"props":3364,"children":3365},{"style":1552},[3366],{"type":112,"value":1579},{"type":106,"tag":1513,"props":3368,"children":3369},{"style":1541},[3370],{"type":112,"value":1560},{"type":106,"tag":1513,"props":3372,"children":3373},{"style":1552},[3374],{"type":112,"value":1588},{"type":106,"tag":1513,"props":3376,"children":3378},{"class":1515,"line":3377},8,[3379,3383,3387,3391,3395,3399,3404,3408],{"type":106,"tag":1513,"props":3380,"children":3381},{"style":1525},[3382],{"type":112,"value":1597},{"type":106,"tag":1513,"props":3384,"children":3385},{"style":1541},[3386],{"type":112,"value":1602},{"type":106,"tag":1513,"props":3388,"children":3389},{"style":1525},[3390],{"type":112,"value":3185},{"type":106,"tag":1513,"props":3392,"children":3393},{"style":1541},[3394],{"type":112,"value":1612},{"type":106,"tag":1513,"props":3396,"children":3397},{"style":1525},[3398],{"type":112,"value":1617},{"type":106,"tag":1513,"props":3400,"children":3401},{"style":1525},[3402],{"type":112,"value":3403}," request_method",{"type":106,"tag":1513,"props":3405,"children":3406},{"style":1525},[3407],{"type":112,"value":1627},{"type":106,"tag":1513,"props":3409,"children":3410},{"style":1525},[3411],{"type":112,"value":1632},{"type":106,"tag":115,"props":3413,"children":3414},{},[3415,3417,3422,3424,3430],{"type":112,"value":3416},"The ",{"type":106,"tag":149,"props":3418,"children":3419},{},[3420],{"type":112,"value":3421},"Firewall\u002FWAF",{"type":112,"value":3423}," with the ",{"type":106,"tag":171,"props":3425,"children":3427},{"className":3426},[],[3428],{"type":112,"value":3429},"vercel-firewall",{"type":112,"value":3431}," skill can be used to manage verified SEO crawlers, block abusive bots, and rate-limit junk traffic before it distorts your hit-rate picture.",{"type":106,"tag":121,"props":3433,"children":3435},{"id":3434},"reducing-isr-cost",[3436],{"type":112,"value":3437},"Reducing ISR cost",{"type":106,"tag":128,"props":3439,"children":3440},{},[3441,3486,3517,3557],{"type":106,"tag":132,"props":3442,"children":3443},{},[3444,3449,3451,3456,3458,3463,3464,3469,3471,3477,3479,3484],{"type":106,"tag":149,"props":3445,"children":3446},{},[3447],{"type":112,"value":3448},"Prefer tag-based over time-based revalidation.",{"type":112,"value":3450}," Replace short ",{"type":106,"tag":171,"props":3452,"children":3454},{"className":3453},[],[3455],{"type":112,"value":82},{"type":112,"value":3457}," intervals with on-demand ",{"type":106,"tag":171,"props":3459,"children":3461},{"className":3460},[],[3462],{"type":112,"value":439},{"type":112,"value":940},{"type":106,"tag":171,"props":3465,"children":3467},{"className":3466},[],[3468],{"type":112,"value":431},{"type":112,"value":3470}," when content changes — time-based regeneration runs whether or not anything changed. If using Cache Components, analyze ",{"type":106,"tag":171,"props":3472,"children":3474},{"className":3473},[],[3475],{"type":112,"value":3476},"cacheLife",{"type":112,"value":3478}," calls with the ",{"type":106,"tag":171,"props":3480,"children":3482},{"className":3481},[],[3483],{"type":112,"value":100},{"type":112,"value":3485}," skill.",{"type":106,"tag":132,"props":3487,"children":3488},{},[3489,3494,3496,3502,3504,3509,3510,3515],{"type":106,"tag":149,"props":3490,"children":3491},{},[3492],{"type":112,"value":3493},"Scope tags to specific IDs.",{"type":112,"value":3495}," Invalidate ",{"type":106,"tag":171,"props":3497,"children":3499},{"className":3498},[],[3500],{"type":112,"value":3501},"blogPost:\u003Cid>",{"type":112,"value":3503},", not a generic ",{"type":106,"tag":171,"props":3505,"children":3507},{"className":3506},[],[3508],{"type":112,"value":2749},{"type":112,"value":325},{"type":106,"tag":171,"props":3511,"children":3513},{"className":3512},[],[3514],{"type":112,"value":1176},{"type":112,"value":3516}," tag — one broad invalidate regenerates everything that carries it.",{"type":106,"tag":132,"props":3518,"children":3519},{},[3520,3522,3527,3528,3533,3535,3541,3543,3549,3551,3556],{"type":112,"value":3521},"Tune the revalidate interval where your framework declares it (Next.js ",{"type":106,"tag":171,"props":3523,"children":3525},{"className":3524},[],[3526],{"type":112,"value":82},{"type":112,"value":940},{"type":106,"tag":171,"props":3529,"children":3531},{"className":3530},[],[3532],{"type":112,"value":3476},{"type":112,"value":3534},", SvelteKit ",{"type":106,"tag":171,"props":3536,"children":3538},{"className":3537},[],[3539],{"type":112,"value":3540},"isr",{"type":112,"value":3542},", Nuxt ",{"type":106,"tag":171,"props":3544,"children":3546},{"className":3545},[],[3547],{"type":112,"value":3548},"routeRules",{"type":112,"value":3550},", Astro). For Next.js Cache Components, see the ",{"type":106,"tag":171,"props":3552,"children":3554},{"className":3553},[],[3555],{"type":112,"value":100},{"type":112,"value":3485},{"type":106,"tag":132,"props":3558,"children":3559},{},[3560,3562,3568],{"type":112,"value":3561},"Use ",{"type":106,"tag":171,"props":3563,"children":3565},{"className":3564},[],[3566],{"type":112,"value":3567},"CDN-Cache-Control",{"type":112,"value":3569}," headers to cache dynamic functions.",{"type":106,"tag":179,"props":3571,"children":3573},{"id":3572},"inspect-one-path",[3574],{"type":112,"value":3575},"Inspect one path",{"type":106,"tag":1502,"props":3577,"children":3579},{"className":1504,"code":3578,"language":1506,"meta":1507,"style":1507},"curl -sSI https:\u002F\u002F\u003Chost>\u002F\u003Cpath> | grep -iE 'x-vercel-cache|x-matched-path|cache-control|vary|age|set-cookie'\n",[3580],{"type":106,"tag":171,"props":3581,"children":3582},{"__ignoreMap":1507},[3583],{"type":106,"tag":1513,"props":3584,"children":3585},{"class":1515,"line":1516},[3586,3590,3595,3600,3605,3610,3614,3618,3622,3626,3631,3636,3640,3645,3650,3655,3660,3665],{"type":106,"tag":1513,"props":3587,"children":3588},{"style":1520},[3589],{"type":112,"value":1075},{"type":106,"tag":1513,"props":3591,"children":3592},{"style":1525},[3593],{"type":112,"value":3594}," -sSI",{"type":106,"tag":1513,"props":3596,"children":3597},{"style":1525},[3598],{"type":112,"value":3599}," https:\u002F\u002F",{"type":106,"tag":1513,"props":3601,"children":3602},{"style":1541},[3603],{"type":112,"value":3604},"\u003C",{"type":106,"tag":1513,"props":3606,"children":3607},{"style":1525},[3608],{"type":112,"value":3609},"hos",{"type":106,"tag":1513,"props":3611,"children":3612},{"style":1552},[3613],{"type":112,"value":1579},{"type":106,"tag":1513,"props":3615,"children":3616},{"style":1541},[3617],{"type":112,"value":1560},{"type":106,"tag":1513,"props":3619,"children":3620},{"style":1525},[3621],{"type":112,"value":325},{"type":106,"tag":1513,"props":3623,"children":3624},{"style":1541},[3625],{"type":112,"value":3604},{"type":106,"tag":1513,"props":3627,"children":3628},{"style":1525},[3629],{"type":112,"value":3630},"pat",{"type":106,"tag":1513,"props":3632,"children":3633},{"style":1552},[3634],{"type":112,"value":3635},"h",{"type":106,"tag":1513,"props":3637,"children":3638},{"style":1541},[3639],{"type":112,"value":1560},{"type":106,"tag":1513,"props":3641,"children":3642},{"style":1541},[3643],{"type":112,"value":3644}," |",{"type":106,"tag":1513,"props":3646,"children":3647},{"style":1520},[3648],{"type":112,"value":3649}," grep",{"type":106,"tag":1513,"props":3651,"children":3652},{"style":1525},[3653],{"type":112,"value":3654}," -iE",{"type":106,"tag":1513,"props":3656,"children":3657},{"style":1541},[3658],{"type":112,"value":3659}," '",{"type":106,"tag":1513,"props":3661,"children":3662},{"style":1525},[3663],{"type":112,"value":3664},"x-vercel-cache|x-matched-path|cache-control|vary|age|set-cookie",{"type":106,"tag":1513,"props":3666,"children":3667},{"style":1541},[3668],{"type":112,"value":3669},"'\n",{"type":106,"tag":115,"props":3671,"children":3672},{},[3673,3675,3680,3682,3687,3688,3693,3694,3700,3702,3711,3713,3719,3721,3727,3729,3735,3737,3742,3744,3750,3752,3758,3760,3765,3766,3771,3773,3778,3779,3784,3785,3791,3793,3799],{"type":112,"value":3674},"This zero-dependency first reach shows the status (",{"type":106,"tag":171,"props":3676,"children":3678},{"className":3677},[],[3679],{"type":112,"value":52},{"type":112,"value":3681},"), the cache directives (",{"type":106,"tag":171,"props":3683,"children":3685},{"className":3684},[],[3686],{"type":112,"value":1974},{"type":112,"value":940},{"type":106,"tag":171,"props":3689,"children":3691},{"className":3690},[],[3692],{"type":112,"value":3567},{"type":112,"value":940},{"type":106,"tag":171,"props":3695,"children":3697},{"className":3696},[],[3698],{"type":112,"value":3699},"Vercel-CDN-Cache-Control",{"type":112,"value":3701},"), and — crucially — ",{"type":106,"tag":149,"props":3703,"children":3704},{},[3705],{"type":106,"tag":171,"props":3706,"children":3708},{"className":3707},[],[3709],{"type":112,"value":3710},"x-matched-path",{"type":112,"value":3712},", which reveals rewrites like ",{"type":106,"tag":171,"props":3714,"children":3716},{"className":3715},[],[3717],{"type":112,"value":3718},"\u002Fprecomputed\u002Fexp~...\u002F...",{"type":112,"value":3720}," that expose experiment\u002Fflag precomputation. ",{"type":106,"tag":171,"props":3722,"children":3724},{"className":3723},[],[3725],{"type":112,"value":3726},"vary",{"type":112,"value":3728}," flags personalization (RSC, cookies); ",{"type":106,"tag":171,"props":3730,"children":3732},{"className":3731},[],[3733],{"type":112,"value":3734},"set-cookie",{"type":112,"value":3736}," forces ",{"type":106,"tag":171,"props":3738,"children":3740},{"className":3739},[],[3741],{"type":112,"value":368},{"type":112,"value":3743},". For a per-phase timing breakdown, ",{"type":106,"tag":171,"props":3745,"children":3747},{"className":3746},[],[3748],{"type":112,"value":3749},"vercel httpstat \u002Fsome\u002Fpath",{"type":112,"value":3751}," (CLI v48.9.0+; needs the ",{"type":106,"tag":171,"props":3753,"children":3755},{"className":3754},[],[3756],{"type":112,"value":3757},"httpstat",{"type":112,"value":3759}," tool installed) adds latency stats. A path that should cache but shows ",{"type":106,"tag":171,"props":3761,"children":3763},{"className":3762},[],[3764],{"type":112,"value":346},{"type":112,"value":325},{"type":106,"tag":171,"props":3767,"children":3769},{"className":3768},[],[3770],{"type":112,"value":368},{"type":112,"value":3772}," usually has ",{"type":106,"tag":171,"props":3774,"children":3776},{"className":3775},[],[3777],{"type":112,"value":687},{"type":112,"value":681},{"type":106,"tag":171,"props":3780,"children":3782},{"className":3781},[],[3783],{"type":112,"value":679},{"type":112,"value":681},{"type":106,"tag":171,"props":3786,"children":3788},{"className":3787},[],[3789],{"type":112,"value":3790},"max-age=0",{"type":112,"value":3792},", a per-request input (cookies\u002Fheaders\u002F",{"type":106,"tag":171,"props":3794,"children":3796},{"className":3795},[],[3797],{"type":112,"value":3798},"searchParams",{"type":112,"value":3800},"), or an uncacheable method (see FAQ).",{"type":106,"tag":115,"props":3802,"children":3803},{},[3804,3809],{"type":106,"tag":149,"props":3805,"children":3806},{},[3807],{"type":112,"value":3808},"Inspect one request.",{"type":112,"value":3810}," When metrics or headers give you a request ID, pull the full log record:",{"type":106,"tag":1502,"props":3812,"children":3814},{"className":1504,"code":3813,"language":1506,"meta":1507,"style":1507},"vercel logs --request-id \u003Crequest-id> --json\n",[3815],{"type":106,"tag":171,"props":3816,"children":3817},{"__ignoreMap":1507},[3818],{"type":106,"tag":1513,"props":3819,"children":3820},{"class":1515,"line":1516},[3821,3825,3830,3835,3839,3844,3849,3853],{"type":106,"tag":1513,"props":3822,"children":3823},{"style":1520},[3824],{"type":112,"value":8},{"type":106,"tag":1513,"props":3826,"children":3827},{"style":1525},[3828],{"type":112,"value":3829}," logs",{"type":106,"tag":1513,"props":3831,"children":3832},{"style":1525},[3833],{"type":112,"value":3834}," --request-id",{"type":106,"tag":1513,"props":3836,"children":3837},{"style":1541},[3838],{"type":112,"value":1544},{"type":106,"tag":1513,"props":3840,"children":3841},{"style":1525},[3842],{"type":112,"value":3843},"request-i",{"type":106,"tag":1513,"props":3845,"children":3846},{"style":1552},[3847],{"type":112,"value":3848},"d",{"type":106,"tag":1513,"props":3850,"children":3851},{"style":1541},[3852],{"type":112,"value":1560},{"type":106,"tag":1513,"props":3854,"children":3855},{"style":1525},[3856],{"type":112,"value":3857}," --json\n",{"type":106,"tag":115,"props":3859,"children":3860},{},[3861,3862,3868],{"type":112,"value":3561},{"type":106,"tag":171,"props":3863,"children":3865},{"className":3864},[],[3866],{"type":112,"value":3867},"--json",{"type":112,"value":3869}," so the agent can parse cache status, path, and timing fields programmatically.",{"type":106,"tag":121,"props":3871,"children":3873},{"id":3872},"faq",[3874],{"type":112,"value":3875},"FAQ",{"type":106,"tag":128,"props":3877,"children":3878},{},[3879,3903,3927],{"type":106,"tag":132,"props":3880,"children":3881},{},[3882,3887,3889,3894,3896,3901],{"type":106,"tag":149,"props":3883,"children":3884},{},[3885],{"type":112,"value":3886},"What are prerender variant misses?",{"type":112,"value":3888}," When a route uses a dynamic param, each distinct cache-key variant is prerendered and cached separately, so each variant misses on its first hit per region and low-traffic ones rarely stay warm. The most common modern cause is ",{"type":106,"tag":149,"props":3890,"children":3891},{},[3892],{"type":112,"value":3893},"feature-flag \u002F experiment precomputation",{"type":112,"value":3895}," — middleware picks a variant per request (",{"type":106,"tag":171,"props":3897,"children":3899},{"className":3898},[],[3900],{"type":112,"value":3718},{"type":112,"value":3902}," paths), and flags × routes × PPR segments multiply into thousands of ISR entries (also a middleware-invocation cost). Fix: collapse the variant matrix (retire finished experiments), or accept the cost.",{"type":106,"tag":132,"props":3904,"children":3905},{},[3906,3911,3913,3918,3920,3925],{"type":106,"tag":149,"props":3907,"children":3908},{},[3909],{"type":112,"value":3910},"Does PPR avoid function invocations?",{"type":112,"value":3912}," No — a PPR route has dynamic holes by definition, so the cached shell hit still runs the function to fill them. (A route with ",{"type":106,"tag":138,"props":3914,"children":3915},{},[3916],{"type":112,"value":3917},"no",{"type":112,"value":3919}," holes is just ISR and serves a pure ",{"type":106,"tag":171,"props":3921,"children":3923},{"className":3922},[],[3924],{"type":112,"value":83},{"type":112,"value":3926}," HIT — see Key concepts.)",{"type":106,"tag":132,"props":3928,"children":3929},{},[3930,3935],{"type":106,"tag":149,"props":3931,"children":3932},{},[3933],{"type":112,"value":3934},"Why are there more function invocations than PPR requests?",{"type":112,"value":3936}," PPR requests have a static shell and a dynamic function invocation. When the static shell needs to be regenerated, it incurs a function invocation on top of the dynamic function for the content.",{"type":106,"tag":121,"props":3938,"children":3940},{"id":3939},"related-skills",[3941],{"type":112,"value":3942},"Related skills",{"type":106,"tag":128,"props":3944,"children":3945},{},[3946,3956,3973],{"type":106,"tag":132,"props":3947,"children":3948},{},[3949,3954],{"type":106,"tag":171,"props":3950,"children":3952},{"className":3951},[],[3953],{"type":112,"value":3429},{"type":112,"value":3955}," — manage verified SEO crawlers, block abusive bots, and rate-limit junk BYPASS traffic.",{"type":106,"tag":132,"props":3957,"children":3958},{},[3959,3965,3967,3971],{"type":106,"tag":171,"props":3960,"children":3962},{"className":3961},[],[3963],{"type":112,"value":3964},"runtime-cache",{"type":112,"value":3966}," — caching data ",{"type":106,"tag":138,"props":3968,"children":3969},{},[3970],{"type":112,"value":142},{"type":112,"value":3972}," (per-region key-value \u002F data cache). A different layer from the CDN\u002FISR caches; use it to cache an API response or query result inside a function.",{"type":106,"tag":132,"props":3974,"children":3975},{},[3976,3981,3983,3989,3990,3995,3996,4002,4003,4008],{"type":106,"tag":171,"props":3977,"children":3979},{"className":3978},[],[3980],{"type":112,"value":100},{"type":112,"value":3982}," — Next.js ",{"type":106,"tag":171,"props":3984,"children":3986},{"className":3985},[],[3987],{"type":112,"value":3988},"use cache",{"type":112,"value":681},{"type":106,"tag":171,"props":3991,"children":3993},{"className":3992},[],[3994],{"type":112,"value":3476},{"type":112,"value":681},{"type":106,"tag":171,"props":3997,"children":3999},{"className":3998},[],[4000],{"type":112,"value":4001},"cacheTag",{"type":112,"value":1444},{"type":106,"tag":171,"props":4004,"children":4006},{"className":4005},[],[4007],{"type":112,"value":82},{"type":112,"value":4009}," tuning (one framework's ISR\u002FPPR controls).",{"type":106,"tag":121,"props":4011,"children":4013},{"id":4012},"references",[4014],{"type":112,"value":4015},"References:",{"type":106,"tag":128,"props":4017,"children":4018},{},[4019,4029,4039,4050,4061,4072,4082],{"type":106,"tag":132,"props":4020,"children":4021},{},[4022,4024],{"type":112,"value":4023},"Caching overview: ",{"type":106,"tag":241,"props":4025,"children":4027},{"href":39,"rel":4026},[245],[4028],{"type":112,"value":39},{"type":106,"tag":132,"props":4030,"children":4031},{},[4032,4034],{"type":112,"value":4033},"ISR: ",{"type":106,"tag":241,"props":4035,"children":4037},{"href":41,"rel":4036},[245],[4038],{"type":112,"value":41},{"type":106,"tag":132,"props":4040,"children":4041},{},[4042,4044],{"type":112,"value":4043},"Partial Prerendering (PPR): ",{"type":106,"tag":241,"props":4045,"children":4048},{"href":4046,"rel":4047},"https:\u002F\u002Fvercel.com\u002Fdocs\u002Fpartial-prerendering",[245],[4049],{"type":112,"value":4046},{"type":106,"tag":132,"props":4051,"children":4052},{},[4053,4055],{"type":112,"value":4054},"Cache-Control headers: ",{"type":106,"tag":241,"props":4056,"children":4059},{"href":4057,"rel":4058},"https:\u002F\u002Fvercel.com\u002Fdocs\u002Fcaching\u002Fcache-control-headers",[245],[4060],{"type":112,"value":4057},{"type":106,"tag":132,"props":4062,"children":4063},{},[4064,4066],{"type":112,"value":4065},"Diagnosing and fixing cache issues (full runbook): ",{"type":106,"tag":241,"props":4067,"children":4070},{"href":4068,"rel":4069},"https:\u002F\u002Fvercel.com\u002Fdocs\u002Fcaching\u002Fcdn-cache\u002Fdebug-cache-issues",[245],[4071],{"type":112,"value":4068},{"type":106,"tag":132,"props":4073,"children":4074},{},[4075,4077],{"type":112,"value":4076},"vercel metrics CLI: ",{"type":106,"tag":241,"props":4078,"children":4080},{"href":42,"rel":4079},[245],[4081],{"type":112,"value":42},{"type":106,"tag":132,"props":4083,"children":4084},{},[4085,4087],{"type":112,"value":4086},"vercel logs CLI: ",{"type":106,"tag":241,"props":4088,"children":4091},{"href":4089,"rel":4090},"https:\u002F\u002Fvercel.com\u002Fdocs\u002Fcli\u002Flogs",[245],[4092],{"type":112,"value":4089},{"type":106,"tag":4094,"props":4095,"children":4096},"style",{},[4097],{"type":112,"value":4098},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"items":4100,"total":4205},[4101,4118,4138,4155,4162,4179,4194],{"slug":4102,"name":4102,"fn":4103,"description":4104,"org":4105,"tags":4106,"stars":23,"repoUrl":24,"updatedAt":4117},"ai-gateway","configure and manage Vercel AI Gateway","Vercel AI Gateway expert guidance. Use when configuring model routing, provider failover, cost tracking, or managing multiple AI providers through a unified API.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4107,4110,4113,4116],{"name":4108,"slug":4109,"type":15},"AI Infrastructure","ai-infrastructure",{"name":4111,"slug":4112,"type":15},"Cost Optimization","cost-optimization",{"name":4114,"slug":4115,"type":15},"LLM","llm",{"name":9,"slug":8,"type":15},"2026-04-06T18:56:06.57787",{"slug":4119,"name":4119,"fn":4120,"description":4121,"org":4122,"tags":4123,"stars":23,"repoUrl":24,"updatedAt":4137},"auth","integrate authentication in Next.js apps","Authentication integration guidance — Clerk (native Vercel Marketplace), Descope, and Auth0 setup for Next.js applications. Covers middleware auth patterns, sign-in\u002Fsign-up flows, and Marketplace provisioning. Use when implementing user authentication.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4124,4127,4130,4133,4136],{"name":4125,"slug":4126,"type":15},"Auth0","auth0",{"name":4128,"slug":4129,"type":15},"Authentication","authentication",{"name":4131,"slug":4132,"type":15},"Next.js","next-js",{"name":4134,"slug":4135,"type":15},"Security","security",{"name":9,"slug":8,"type":15},"2026-04-06T18:56:17.050565",{"slug":4139,"name":4139,"fn":4140,"description":4141,"org":4142,"tags":4143,"stars":23,"repoUrl":24,"updatedAt":4154},"bootstrap","bootstrap Vercel-linked repositories","Project bootstrapping orchestrator for repos that depend on Vercel-linked resources (databases, auth, and managed integrations). Use when setting up or repairing a repository so linking, environment provisioning, env pulls, and first-run db\u002Fdev commands happen in the correct safe order.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4144,4147,4150,4153],{"name":4145,"slug":4146,"type":15},"Configuration","configuration",{"name":4148,"slug":4149,"type":15},"Deployment","deployment",{"name":4151,"slug":4152,"type":15},"Local Development","local-development",{"name":9,"slug":8,"type":15},"2026-04-06T18:56:18.297868",{"slug":4,"name":4,"fn":5,"description":6,"org":4156,"tags":4157,"stars":23,"repoUrl":24,"updatedAt":25},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4158,4159,4160,4161],{"name":21,"slug":22,"type":15},{"name":13,"slug":14,"type":15},{"name":17,"slug":18,"type":15},{"name":9,"slug":8,"type":15},{"slug":4163,"name":4163,"fn":4164,"description":4165,"org":4166,"tags":4167,"stars":23,"repoUrl":24,"updatedAt":4178},"chat-sdk","build multi-platform chatbots with Vercel","Vercel Chat SDK expert guidance. Use when building multi-platform chat bots — Slack, Telegram, Microsoft Teams, Discord, Google Chat, GitHub, Linear — with a single codebase. Covers the Chat class, adapters, threads, messages, cards, modals, streaming, state management, and webhook setup.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4168,4171,4174,4177],{"name":4169,"slug":4170,"type":15},"Agents","agents",{"name":4172,"slug":4173,"type":15},"Messaging","messaging",{"name":4175,"slug":4176,"type":15},"SDK","sdk",{"name":9,"slug":8,"type":15},"2026-04-06T18:56:26.921901",{"slug":4180,"name":4180,"fn":4181,"description":4182,"org":4183,"tags":4184,"stars":23,"repoUrl":24,"updatedAt":4193},"deployments-cicd","manage Vercel deployments and CI\u002FCD","Vercel deployment and CI\u002FCD expert guidance. Use when deploying, promoting, rolling back, inspecting deployments, building with --prebuilt, or configuring CI workflow files for Vercel.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4185,4188,4189,4192],{"name":4186,"slug":4187,"type":15},"CI\u002FCD","ci-cd",{"name":4148,"slug":4149,"type":15},{"name":4190,"slug":4191,"type":15},"Operations","operations",{"name":9,"slug":8,"type":15},"2026-04-06T18:56:22.054263",{"slug":4195,"name":4195,"fn":4196,"description":4197,"org":4198,"tags":4199,"stars":23,"repoUrl":24,"updatedAt":4204},"env-vars","manage Vercel environment variables","Vercel environment variable expert guidance. Use when working with .env files, vercel env commands, OIDC tokens, or managing environment-specific configuration.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4200,4201,4202,4203],{"name":4145,"slug":4146,"type":15},{"name":4190,"slug":4191,"type":15},{"name":4134,"slug":4135,"type":15},{"name":9,"slug":8,"type":15},"2026-04-06T18:56:28.150777",29,{"items":4207,"total":4370},[4208,4226,4238,4255,4266,4279,4295,4309,4321,4340,4350,4360],{"slug":4209,"name":4209,"fn":4210,"description":4211,"org":4212,"tags":4213,"stars":4223,"repoUrl":4224,"updatedAt":4225},"next-cache-components-adoption","enable and migrate to Next.js Cache Components","Turn on Cache Components in a Next.js app and resolve the blocking routes it surfaces. Use when the user wants to enable, adopt, or migrate to Cache Components, flip the `cacheComponents` flag, work through a flood of blocking-prerender \u002F instant validation errors, run the `cache-components-instant-false` codemod, or decide between opting routes out with `export const instant = false` and fixing them in place.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4214,4215,4218,4221,4222],{"name":21,"slug":22,"type":15},{"name":4216,"slug":4217,"type":15},"Frontend","frontend",{"name":4219,"slug":4220,"type":15},"Migration","migration",{"name":4131,"slug":4132,"type":15},{"name":9,"slug":8,"type":15},141208,"https:\u002F\u002Fgithub.com\u002Fvercel\u002Fnext.js","2026-07-24T05:38:30.118542",{"slug":4227,"name":4227,"fn":4228,"description":4229,"org":4230,"tags":4231,"stars":4223,"repoUrl":4224,"updatedAt":4237},"next-cache-components-optimizer","optimize Next.js cache components","Drive a Next.js route to instant navigation by setting up an agentic loop, under Cache Components \u002F PPR, on initial load (hard navigation) and client-side navigation (soft navigation). Encode the goal as a failing @next\u002Fplaywright instant() e2e and work it to green, one verified route at a time; the shipped test then guards against regression. Use when asked to make a route's navigation instant (its static shell commits immediately), fix a route whose static shell isn't prerendered\u002Fserved\u002Fprefetched, grow a route's static shell or fix its slow first paint, diagnose which Suspense boundary keeps a route out of its static shell, or write the instant() e2e guard for one. Requires Next.js 16.3+ with cacheComponents; directs an upgrade if older.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4232,4233,4234,4235,4236],{"name":21,"slug":22,"type":15},{"name":4216,"slug":4217,"type":15},{"name":4131,"slug":4132,"type":15},{"name":17,"slug":18,"type":15},{"name":9,"slug":8,"type":15},"2026-07-30T05:31:10.674078",{"slug":4239,"name":4239,"fn":4240,"description":4241,"org":4242,"tags":4243,"stars":4223,"repoUrl":4224,"updatedAt":4254},"next-dev-loop","verify Next.js runtime behavior","Verify Next.js runtime behavior after editing app code. Use this skill to confirm a change actually works in a running app — not just that it compiles or type-checks. Combines \u002F_next\u002Fmcp (Next.js's view) with agent-browser (the browser's view). Requires a running `next dev`.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4244,4247,4248,4249,4250,4251],{"name":4245,"slug":4246,"type":15},"Debugging","debugging",{"name":4216,"slug":4217,"type":15},{"name":4151,"slug":4152,"type":15},{"name":4131,"slug":4132,"type":15},{"name":9,"slug":8,"type":15},{"name":4252,"slug":4253,"type":15},"Web Development","web-development","2026-05-22T06:45:28.627735",{"slug":4256,"name":4256,"fn":4257,"description":4258,"org":4259,"tags":4260,"stars":4223,"repoUrl":4224,"updatedAt":4265},"next-partial-prefetching-adoption","adopt Partial Prefetching in Next.js apps","Turn on Partial Prefetching in a Next.js app and work through the insights it surfaces. Use when the user wants to enable or adopt Partial Prefetching, flip the `partialPrefetching` flag, opt routes in with `export const prefetch = 'partial'`, audit `\u003CLink prefetch={true}>` calls, or resolve the link-prefetch-partial and instant-shell-url-data insights.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4261,4262,4263,4264],{"name":4216,"slug":4217,"type":15},{"name":4131,"slug":4132,"type":15},{"name":17,"slug":18,"type":15},{"name":9,"slug":8,"type":15},"2026-07-30T05:31:11.591864",{"slug":4267,"name":4267,"fn":4268,"description":4269,"org":4270,"tags":4271,"stars":4276,"repoUrl":4277,"updatedAt":4278},"turborepo","manage monorepos with Turborepo","Turborepo monorepo build system guidance. Triggers on: turbo.json, task pipelines,\ndependsOn, caching, remote cache, the \"turbo\" CLI, --filter, --affected, CI optimization, environment\nvariables, internal packages, monorepo structure\u002Fbest practices, and boundaries.\n\nUse when user: configures tasks\u002Fworkflows\u002Fpipelines, creates packages, sets up\nmonorepo, shares code between apps, runs changed\u002Faffected packages, debugs cache,\nor has apps\u002Fpackages directories.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4272,4273,4274],{"name":4186,"slug":4187,"type":15},{"name":17,"slug":18,"type":15},{"name":4275,"slug":4267,"type":15},"Turborepo",30809,"https:\u002F\u002Fgithub.com\u002Fvercel\u002Fturborepo","2026-07-30T05:32:14.920116",{"slug":4280,"name":4280,"fn":4281,"description":4282,"org":4283,"tags":4284,"stars":4292,"repoUrl":4293,"updatedAt":4294},"add-function-examples","add AI function examples for testing","Guide for adding new AI function examples, for testing specific features against the actual provider APIs.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4285,4288,4291],{"name":4286,"slug":4287,"type":15},"AI SDK","ai-sdk",{"name":4289,"slug":4290,"type":15},"Testing","testing",{"name":9,"slug":8,"type":15},25670,"https:\u002F\u002Fgithub.com\u002Fvercel\u002Fai","2026-04-06T18:55:51.318866",{"slug":4296,"name":4296,"fn":4297,"description":4298,"org":4299,"tags":4300,"stars":4292,"repoUrl":4293,"updatedAt":4308},"add-harness-package","add AI SDK harness packages","Guide for adding new AI SDK harness packages. Use when creating a new @ai-sdk\u002Fharness-\u003Cname> package that adapts a coding-agent runtime to HarnessV1.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4301,4302,4303,4306,4307],{"name":4169,"slug":4170,"type":15},{"name":4286,"slug":4287,"type":15},{"name":4304,"slug":4305,"type":15},"Harness","harness",{"name":4175,"slug":4176,"type":15},{"name":9,"slug":8,"type":15},"2026-06-18T08:29:19.858737",{"slug":4310,"name":4310,"fn":4311,"description":4312,"org":4313,"tags":4314,"stars":4292,"repoUrl":4293,"updatedAt":4320},"add-provider-package","add new provider packages to AI SDK","Guide for adding new AI provider packages to the AI SDK. Use when creating a new @ai-sdk\u002F\u003Cprovider> package to integrate an AI service into the SDK.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4315,4316,4319],{"name":4286,"slug":4287,"type":15},{"name":4317,"slug":4318,"type":15},"API Development","api-development",{"name":9,"slug":8,"type":15},"2026-04-06T18:55:47.45549",{"slug":4322,"name":4322,"fn":4323,"description":4324,"org":4325,"tags":4326,"stars":4292,"repoUrl":4293,"updatedAt":4339},"adr-skill","create and maintain architecture decision records","Create and maintain Architecture Decision Records (ADRs) optimized for agentic coding workflows. Use when you need to propose, write, update, accept\u002Freject, deprecate, or supersede an ADR; bootstrap an adr folder and index; consult existing ADRs before implementing changes; or enforce ADR conventions. This skill uses Socratic questioning to capture intent before drafting, and validates output against an agent-readiness checklist.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4327,4330,4333,4336],{"name":4328,"slug":4329,"type":15},"ADR","adr",{"name":4331,"slug":4332,"type":15},"Architecture","architecture",{"name":4334,"slug":4335,"type":15},"Documentation","documentation",{"name":4337,"slug":4338,"type":15},"Engineering","engineering","2026-04-06T18:55:50.043694",{"slug":4287,"name":4287,"fn":4341,"description":4342,"org":4343,"tags":4344,"stars":4292,"repoUrl":4293,"updatedAt":4349},"build AI features with Vercel AI SDK","Answer questions about the AI SDK and help build AI-powered features. Use when developers: (1) Ask about AI SDK functions like generateText, streamText, ToolLoopAgent, embed, or tools, (2) Want to build AI agents, chatbots, RAG systems, or text generation features, (3) Have questions about AI providers (OpenAI, Anthropic, Google, etc.), streaming, tool calling, structured output, or embeddings, (4) Use React hooks like useChat or useCompletion. Triggers on: \"AI SDK\", \"Vercel AI SDK\", \"generateText\", \"streamText\", \"add AI to my app\", \"build an agent\", \"tool calling\", \"structured output\", \"useChat\".",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4345,4346,4347,4348],{"name":4169,"slug":4170,"type":15},{"name":4286,"slug":4287,"type":15},{"name":4114,"slug":4115,"type":15},{"name":9,"slug":8,"type":15},"2026-04-06T18:55:48.739463",{"slug":4351,"name":4351,"fn":4352,"description":4353,"org":4354,"tags":4355,"stars":4292,"repoUrl":4293,"updatedAt":4359},"capture-api-response-test-fixture","capture API response test fixtures","Capture API response test fixture.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4356,4357,4358],{"name":4317,"slug":4318,"type":15},{"name":4289,"slug":4290,"type":15},{"name":9,"slug":8,"type":15},"2026-04-06T18:55:56.374433",{"slug":4361,"name":4361,"fn":4362,"description":4363,"org":4364,"tags":4365,"stars":4292,"repoUrl":4293,"updatedAt":4369},"develop-ai-functions-example","develop AI SDK function examples","Develop examples for AI SDK functions. Use when creating, running, or modifying examples under examples\u002Fai-functions\u002Fsrc to validate provider support, demonstrate features, or create test fixtures.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4366,4367,4368],{"name":4286,"slug":4287,"type":15},{"name":4289,"slug":4290,"type":15},{"name":9,"slug":8,"type":15},"2026-04-06T18:55:55.088956",68]