Update to Vercel
Snapshot Oct 6, 2026 · 18:03 UTC · version 0.54.1
Collection source: downloaded plugin package. These snapshots do not have a confirmed matching collection source. Differences in file lists alone do not establish changes to the package.
Instructions updated for runtime-cache
Instruction wording changed from “"https://nextjs.org/docs/app/building-your-application/caching"” to “"https://nextjs.org/docs/app/api-reference/directives/use-cache-remote"”. 37 additional added or edited lines are in the evidence.
Observed in instructions or declared skills. Runtime behavior has not been tested.
Skill instructions
"https://nextjs.org/docs/app/building-your-application/caching" - **Isolated**: Scoped per project AND per deployment environment (`preview` vs `production`) | Tags per Runtime Cache item | 64 | - 📖 docs: https://vercel.com/docs/runtime-...
"https://nextjs.org/docs/app/api-reference/directives/use-cache-remote" validate: - pattern: 'from\s+[''""](redis|ioredis)[''""]|require\s*\(\s*[''""](redis|ioredis)[''""]|new\s+Redis\(' message: 'Direct Redis/ioredis client de...
Compare saved observations
Download comparison JSONFull technical diff · 1 changed fields
changed /skill_md_contents
"---\nname: runtime-cache\ndescription: Vercel Runtime Cache API guidance — ephemeral per-region key-value cache with tag-based invalidation. Shared across Functions, Routing Middleware, and Builds. Use when implementing caching strategies beyond framework-level caching.\nmetadata:\n priority: 6\n docs:\n - \"https://nextjs.org/docs/app/building-your-application/caching\"\n sitemap: \"https://nextjs.org/sitemap.xml\"\n pathPatterns: \n - 'lib/cache/**'\n - 'src/lib/cache/**'\n - 'lib/cache.*'\n - 'src/lib/cache.*'\n bashPatterns:\n - '\\bnpm\\s+(install|i|add)\\s+[^\\n]*@vercel/functions\\b'\n - '\\bpnpm\\s+(install|i|add)\\s+[^\\n]*@vercel/functions\\b'\n - '\\bbun\\s+(install|i|add)\\s+[^\\n]*@vercel/functions\\b'\n - '\\byarn\\s+add\\s+[^\\n]*@vercel/functions\\b'\n---\n\n# Vercel Runtime Cache API\n\nYou are an expert in the Vercel Runtime Cache — an ephemeral caching layer for serverless compute.\n\n## What It Is\n\nThe Runtime Cache is a **per-region key-value store** accessible from Vercel Functions, Routing Middleware, and Builds. It supports **tag-based invalidation** for granular cache control.\n\n- **Regional**: Each Vercel region has its own isolated cache\n- **Isolated**: Scoped per project AND per deployment environment (`preview` vs `production`)\n- **Persistent across deployments**: Cached data survives new deploys; invalidation via TTL or `expireTag`\n- **Ephemeral**: Fixed storage limit per project; LRU eviction when full\n- **Framework-agnostic**: Works with any framework via `@vercel/functions`\n\n## Key APIs\n\nAll APIs from `@vercel/functions`:\n\n### Basic Cache Operations\n\n```ts\nimport { getCache } from '@vercel/functions';\n\nconst cache = getCache();\n\n// Store data with TTL and tags\nawait cache.set('user:123', userData, {\n ttl: 3600, // seconds\n tags: ['users', 'user:123'], // for bulk invalidation\n name: 'user-profile', // human-readable label for observability\n});\n\n// Retrieve cached data (returns value or undefined)\nconst data = await cache.get('user:123');\n\n// Delete a specific key\nawait cache.delete('user:123');\n\n// Expire all entries with a tag (propagates globally within 300ms)\nawait cache.expireTag('users');\nawait cache.expireTag(['users', 'user:123']); // multiple tags\n```\n\n### Cache Options\n\n```ts\nconst cache = getCache({\n namespace: 'api', // prefix for keys\n namespaceSeparator: ':', // separator (default)\n keyHashFunction: (key) => sha256(key), // custom key hashing\n});\n```\n\n### Full Example (Framework-Agnostic)\n\n```ts\nimport { getCache } from '@vercel/functions';\n\nexport default {\n async fetch(request: Request) {\n const cache = getCache();\n const cached = await cache.get('blog-posts');\n\n if (cached) {\n return Response.json(cached);\n }\n\n const posts = await fetch('https://api.example.com/posts').then(r => r.json());\n\n await cache.set('blog-posts', posts, {\n ttl: 3600,\n tags: ['blog'],\n });\n\n return Response.json(posts);\n },\n};\n```\n\n### Tag Expiration from Server Action\n\n```ts\n'use server';\nimport { getCache } from '@vercel/functions';\n\nexport async function invalidateBlog() {\n await getCache().expireTag('blog');\n}\n```\n\n## CDN Cache Purging Functions\n\nThese purge across **all three cache layers** (CDN + Runtime Cache + Data Cache):\n\n```ts\nimport { invalidateByTag, dangerouslyDeleteByTag } from '@vercel/functions';\n\n// Stale-while-revalidate: serves stale, revalidates in background\nawait invalidateByTag('blog-posts');\n\n// Hard delete: next request blocks while fetching from origin (cache stampede risk)\nawait dangerouslyDeleteByTag('blog-posts', {\n revalidationDeadlineSeconds: 3600,\n});\n```\n\n**Important distinction**:\n- `cache.expireTag()` — operates on Runtime Cache only\n- `invalidateByTag()` / `dangerouslyDeleteByTag()` — purges CDN + Runtime + Data caches\n\n## Next.js Integration\n\n### Next.js 16+ (`use cache: remote`)\n\n```ts\n// next.config.ts\nconst nextConfig: NextConfig = { cacheComponents: true };\n```\n\n```ts\nimport { cacheLife, cacheTag } from 'next/cache';\n\nasync function getData() {\n 'use cache: remote' // stores in Vercel Runtime Cache\n cacheTag('example-tag')\n cacheLife({ expire: 3600 })\n return fetch('https://api.example.com/data').then(r => r.json());\n}\n```\n\n- `'use cache'` (no `: remote`) — in-memory only, ephemeral per instance\n- `'use cache: remote'` — stores in Vercel Runtime Cache\n\n### Next.js 16 Invalidation APIs\n\n| Function | Context | Behavior |\n|----------|---------|----------|\n| `updateTag(tag)` | Server Actions only | Immediate expiration, read-your-own-writes |\n| `revalidateTag(tag, 'max')` | Server Actions + Route Handlers | Stale-while-revalidate (recommended) |\n| `revalidateTag(tag, { expire: 0 })` | Route Handlers (webhooks) | Immediate expiration from external triggers |\n\n**Important**: Single-argument `revalidateTag(tag)` is deprecated in Next.js 16. Always pass a `cacheLife` profile as the second argument.\n\n### Runtime Cache vs ISR Isolation\n\n- Runtime Cache tags do **NOT** apply to ISR pages\n- `cache.expireTag` does **NOT** invalidate ISR cache\n- Next.js `revalidatePath` / `revalidateTag` does **NOT** invalidate Runtime Cache\n- To manage both, use same tag and purge via `invalidateByTag` (hits all cache layers)\n\n## CLI Cache Commands\n\n```bash\n# Purge all cached data\nvercel cache purge # CDN + Data cache\nvercel cache purge --type cdn # CDN only\nvercel cache purge --type data # Data cache only\nvercel cache purge --yes # skip confirmation\n\n# Invalidate by tag (stale-while-revalidate)\nvercel cache invalidate --tag blog-posts,user-profiles\n\n# Hard delete by tag (blocks until revalidated)\nvercel cache dangerously-delete --tag blog-posts\nvercel cache dangerously-delete --tag blog-posts --revalidation-deadline-seconds 3600\n\n# Image invalidation\nvercel cache invalidate --srcimg /images/hero.jpg\n```\n\nNote: `--tag` and `--srcimg` cannot be used together.\n\n## CDN Cache Tags\n\nAdd tags to CDN cached responses for later invalidation:\n\n```ts\nimport { addCacheTag } from '@vercel/functions';\n\n// Via helper\naddCacheTag('product-123');\n\n// Via response header\nreturn Response.json(product, {\n headers: {\n 'Vercel-CDN-Cache-Control': 'public, max-age=86400',\n 'Vercel-Cache-Tag': 'product-123,products',\n },\n});\n```\n\n## Limits\n\n| Property | Limit |\n|----------|-------|\n| Item size | 2 MB |\n| Tags per Runtime Cache item | 64 |\n| Tags per CDN item | 128 |\n| Max tag length | 256 bytes |\n| Tags per bulk REST API call | 16 |\n\nTags are **case-sensitive** and **cannot contain commas**.\n\n## Observability\n\nMonitor hit rates, invalidation patterns, and storage usage in the Vercel Dashboard under **Observability → Runtime Cache**. The CDN dashboard (March 5, 2026) provides a unified view of global traffic distribution, cache performance metrics, a redesigned purging interface, and **project-level routing** — update response headers or rewrite to external APIs without triggering a new deployment. Project-level routes are available on all plans and take effect instantly.\n\n## When to Use\n\n- Caching API responses or computed data across functions in a region\n- Tag-based invalidation when content changes (CMS webhook → expire tag)\n- Reducing database load for frequently accessed data\n- Cross-function data sharing within a region\n\n## When NOT to Use\n\n- Framework-level page caching → use Next.js Cache Components (`'use cache'`)\n- Persistent storage → use a database (Neon, Upstash)\n- CDN-level full response caching → use `Cache-Control` / `Vercel-CDN-Cache-Control` headers\n- Cross-region shared state → use a database\n- User-specific data that differs per request\n\n## References\n\n- 📖 docs: https://vercel.com/docs/runtime-cache\n- 📖 changelog: https://vercel.com/changelog/introducing-the-runtime-cache-api\n- 📖 CLI cache: https://vercel.com/docs/cli/cache\n- 📖 CDN cache purging: https://vercel.com/docs/cdn-cache/purge\n""---\nname: runtime-cache\ndescription: Vercel Runtime Cache API guidance — ephemeral per-region key-value cache with tag-based invalidation. Shared across Functions, Routing Middleware, and Builds. Use when implementing caching strategies beyond framework-level caching.\nmetadata:\n priority: 6\n docs:\n - \"https://nextjs.org/docs/app/api-reference/directives/use-cache-remote\"\n sitemap: \"https://nextjs.org/sitemap.xml\"\n pathPatterns: \n - 'lib/cache/**'\n - 'src/lib/cache/**'\n - 'lib/cache.*'\n - 'src/lib/cache.*'\n bashPatterns:\n - '\\bnpm\\s+(install|i|add)\\s+[^\\n]*@vercel/functions\\b'\n - '\\bpnpm\\s+(install|i|add)\\s+[^\\n]*@vercel/functions\\b'\n - '\\bbun\\s+(install|i|add)\\s+[^\\n]*@vercel/functions\\b'\n - '\\byarn\\s+add\\s+[^\\n]*@vercel/functions\\b'\nvalidate:\n -\n pattern: 'from\\s+[''\"\"](redis|ioredis)[''\"\"]|require\\s*\\(\\s*[''\"\"](redis|ioredis)[''\"\"]|new\\s+Redis\\('\n message: 'Direct Redis/ioredis client detected. Use Upstash Redis (@upstash/redis) for serverless-native Redis with HTTP-based connections.'\n severity: recommended\n upgradeToSkill: vercel-storage\n upgradeWhy: 'Replace direct Redis/ioredis with @upstash/redis for serverless-compatible HTTP-based Redis that works without persistent TCP connections.'\n skipIfFileContains: 'from\\s+[''\"\"]\\@upstash/redis[''\"\"]'\nretrieval:\n aliases:\n - cache api\n - kv cache\n - region cache\n - tag invalidation\n intents:\n - add caching\n - cache api response\n - invalidate cache\n - set up runtime cache\n entities:\n - Runtime Cache\n - tag-based invalidation\n - key-value\n - cache\nchainTo:\n -\n pattern: 'from\\s+[''\"\"]@vercel/kv[''\"\"]'\n targetSkill: vercel-storage\n message: '@vercel/kv is sunset — loading Vercel Storage guidance for Upstash Redis migration.'\n -\n pattern: 'from\\s+[''\"\"]ioredis[''\"\"]|new\\s+Redis\\('\n targetSkill: vercel-storage\n message: 'Direct Redis client detected — loading Vercel Storage guidance for Upstash Redis (serverless-native) integration.'\n\n---\n\n# Vercel Runtime Cache API\n\nYou are an expert in the Vercel Runtime Cache — an ephemeral caching layer for serverless compute.\n\n## What It Is\n\nThe Runtime Cache is a **per-region key-value store** accessible from Vercel Functions, Routing Middleware, and Builds. It supports **tag-based invalidation** for granular cache control.\n\n- **Regional**: Each Vercel region has its own isolated cache\n- **Isolated**: Scoped per deployment environment (`preview` vs `production`); scoped per project on Pro/Enterprise, but shared across all projects on a Hobby team\n- **Persistent across deployments**: Cached data survives new deploys; invalidation via TTL or `expireTag`\n- **Ephemeral**: Fixed storage limit per project; LRU eviction when full\n- **Framework-agnostic**: Works with any framework via `@vercel/functions`\n\n## Key APIs\n\nAll APIs from `@vercel/functions`:\n\n### Basic Cache Operations\n\n```ts\nimport { getCache } from '@vercel/functions';\n\nconst cache = getCache();\n\n// Store data with TTL and tags\nawait cache.set('user:123', userData, {\n ttl: 3600, // seconds\n tags: ['users', 'user:123'], // for bulk invalidation\n name: 'user-profile', // human-readable label for observability\n});\n\n// Retrieve cached data (returns value or undefined)\nconst data = await cache.get('user:123');\n\n// Delete a specific key\nawait cache.delete('user:123');\n\n// Expire all entries with a tag (propagates globally within 300ms)\nawait cache.expireTag('users');\nawait cache.expireTag(['users', 'user:123']); // multiple tags\n```\n\n### Cache Options\n\n```ts\nconst cache = getCache({\n namespace: 'api', // prefix for keys\n namespaceSeparator: ':', // separator (default)\n keyHashFunction: (key) => sha256(key), // custom key hashing\n});\n```\n\n### Full Example (Framework-Agnostic)\n\n```ts\nimport { getCache } from '@vercel/functions';\n\nexport default {\n async fetch(request: Request) {\n const cache = getCache();\n const cached = await cache.get('blog-posts');\n\n if (cached) {\n return Response.json(cached);\n }\n\n const posts = await fetch('https://api.example.com/posts').then(r => r.json());\n\n await cache.set('blog-posts', posts, {\n ttl: 3600,\n tags: ['blog'],\n });\n\n return Response.json(posts);\n },\n};\n```\n\n### Tag Expiration from Server Action\n\n```ts\n'use server';\nimport { getCache } from '@vercel/functions';\n\nexport async function invalidateBlog() {\n await getCache().expireTag('blog');\n}\n```\n\n## CDN Cache Purging Functions\n\nThese purge across **all three cache layers** (CDN + Runtime Cache + Data Cache):\n\n```ts\nimport { invalidateByTag, dangerouslyDeleteByTag } from '@vercel/functions';\n\n// Stale-while-revalidate: serves stale, revalidates in background\nawait invalidateByTag('blog-posts');\n\n// Hard delete: next request blocks while fetching from origin (cache stampede risk)\nawait dangerouslyDeleteByTag('blog-posts', {\n revalidationDeadlineSeconds: 3600,\n});\n```\n\n**Important distinction**:\n- `cache.expireTag()` — operates on Runtime Cache only\n- `invalidateByTag()` / `dangerouslyDeleteByTag()` — purges CDN + Runtime + Data caches\n\n## Next.js Integration\n\n### Next.js 16+ (`use cache: remote`)\n\n```ts\n// next.config.ts\nconst nextConfig: NextConfig = { cacheComponents: true };\n```\n\n```ts\nimport { cacheLife, cacheTag } from 'next/cache';\n\nasync function getData() {\n 'use cache: remote' // stores in Vercel Runtime Cache\n cacheTag('example-tag')\n cacheLife({ expire: 3600 })\n return fetch('https://api.example.com/data').then(r => r.json());\n}\n```\n\n- `'use cache'` (no `: remote`) — in-memory only, ephemeral per instance\n- `'use cache: remote'` — stores in Vercel Runtime Cache\n\n### Next.js 16 Invalidation APIs\n\n| Function | Context | Behavior |\n|----------|---------|----------|\n| `updateTag(tag)` | Server Actions only | Immediate expiration, read-your-own-writes |\n| `revalidateTag(tag, 'max')` | Server Actions + Route Handlers | Stale-while-revalidate (recommended) |\n| `revalidateTag(tag, { expire: 0 })` | Route Handlers (webhooks) | Immediate expiration from external triggers |\n\n**Important**: Single-argument `revalidateTag(tag)` is deprecated in Next.js 16. Always pass a `cacheLife` profile as the second argument.\n\n### Runtime Cache vs ISR Isolation\n\n- Runtime Cache tags do **NOT** apply to ISR pages\n- `cache.expireTag` does **NOT** invalidate ISR cache\n- Next.js `revalidatePath` / `revalidateTag` does **NOT** invalidate Runtime Cache\n- To manage both, use same tag and purge via `invalidateByTag` (hits all cache layers)\n\n## CLI Cache Commands\n\n```bash\n# Purge all cached data\nvercel cache purge # CDN + Data cache\nvercel cache purge --type cdn # CDN only\nvercel cache purge --type data # Data cache only\nvercel cache purge --yes # skip confirmation\n\n# Invalidate by tag (stale-while-revalidate)\nvercel cache invalidate --tag blog-posts,user-profiles\n\n# Hard delete by tag (blocks until revalidated)\nvercel cache dangerously-delete --tag blog-posts\nvercel cache dangerously-delete --tag blog-posts --revalidation-deadline-seconds 3600\n\n# Image invalidation\nvercel cache invalidate --srcimg /images/hero.jpg\n```\n\nNote: `--tag` and `--srcimg` cannot be used together.\n\n## CDN Cache Tags\n\nAdd tags to CDN cached responses for later invalidation:\n\n```ts\nimport { addCacheTag } from '@vercel/functions';\n\n// Via helper\naddCacheTag('product-123');\n\n// Via response header\nreturn Response.json(product, {\n headers: {\n 'Vercel-CDN-Cache-Control': 'public, max-age=86400',\n 'Vercel-Cache-Tag': 'product-123,products',\n },\n});\n```\n\n## Limits\n\n| Property | Limit |\n|----------|-------|\n| Item size | 2 MB |\n| Tags per Runtime Cache item | 128 |\n| Tags per CDN item | 128 |\n| Max tag length | 256 bytes |\n| Tags per bulk REST API call | 16 |\n\nTags are **case-sensitive** and **cannot contain commas**.\n\n## Observability\n\nMonitor hit rates, invalidation patterns, and storage usage in the Vercel Dashboard under **Observability → Runtime Cache**. The CDN dashboard (March 5, 2026) provides a unified view of global traffic distribution, cache performance metrics, a redesigned purging interface, and **project-level routing** — update response headers or rewrite to external APIs without triggering a new deployment. Project-level routes are available on all plans and take effect instantly.\n\n## When to Use\n\n- Caching API responses or computed data across functions in a region\n- Tag-based invalidation when content changes (CMS webhook → expire tag)\n- Reducing database load for frequently accessed data\n- Cross-function data sharing within a region\n\n## When NOT to Use\n\n- Framework-level page caching → use Next.js Cache Components (`'use cache'`)\n- Persistent storage → use a database (Neon, Upstash)\n- CDN-level full response caching → use `Cache-Control` / `Vercel-CDN-Cache-Control` headers\n- Cross-region shared state → use a database\n- User-specific data that differs per request\n\n## References\n\n- 📖 docs: https://vercel.com/docs/caching/runtime-cache\n- 📖 changelog: https://vercel.com/changelog/introducing-the-runtime-cache-api\n- 📖 CLI cache: https://vercel.com/docs/cli/cache\n- 📖 CDN cache purging: https://vercel.com/docs/caching/cdn-cache/purge\n"SKILL.md line diff
--- before +++ after @@ -4,7 +4,7 @@ metadata: priority: 6 docs: - - "https://nextjs.org/docs/app/building-your-application/caching" + - "https://nextjs.org/docs/app/api-reference/directives/use-cache-remote" sitemap: "https://nextjs.org/sitemap.xml" pathPatterns: - 'lib/cache/**' @@ -16,6 +16,40 @@ - '\bpnpm\s+(install|i|add)\s+[^\n]*@vercel/functions\b' - '\bbun\s+(install|i|add)\s+[^\n]*@vercel/functions\b' - '\byarn\s+add\s+[^\n]*@vercel/functions\b' +validate: + - + pattern: 'from\s+[''""](redis|ioredis)[''""]|require\s*\(\s*[''""](redis|ioredis)[''""]|new\s+Redis\(' + message: 'Direct Redis/ioredis client detected. Use Upstash Redis (@upstash/redis) for serverless-native Redis with HTTP-based connections.' + severity: recommended + upgradeToSkill: vercel-storage + upgradeWhy: 'Replace direct Redis/ioredis with @upstash/redis for serverless-compatible HTTP-based Redis that works without persistent TCP connections.' + skipIfFileContains: 'from\s+[''""]\@upstash/redis[''""]' +retrieval: + aliases: + - cache api + - kv cache + - region cache + - tag invalidation + intents: + - add caching + - cache api response + - invalidate cache + - set up runtime cache + entities: + - Runtime Cache + - tag-based invalidation + - key-value + - cache +chainTo: + - + pattern: 'from\s+[''""]@vercel/kv[''""]' + targetSkill: vercel-storage + message: '@vercel/kv is sunset — loading Vercel Storage guidance for Upstash Redis migration.' + - + pattern: 'from\s+[''""]ioredis[''""]|new\s+Redis\(' + targetSkill: vercel-storage + message: 'Direct Redis client detected — loading Vercel Storage guidance for Upstash Redis (serverless-native) integration.' + --- # Vercel Runtime Cache API @@ -27,7 +61,7 @@ The Runtime Cache is a **per-region key-value store** accessible from Vercel Functions, Routing Middleware, and Builds. It supports **tag-based invalidation** for granular cache control. - **Regional**: Each Vercel region has its own isolated cache -- **Isolated**: Scoped per project AND per deployment environment (`preview` vs `production`) +- **Isolated**: Scoped per deployment environment (`preview` vs `production`); scoped per project on Pro/Enterprise, but shared across all projects on a Hobby team - **Persistent across deployments**: Cached data survives new deploys; invalidation via TTL or `expireTag` - **Ephemeral**: Fixed storage limit per project; LRU eviction when full - **Framework-agnostic**: Works with any framework via `@vercel/functions` @@ -214,7 +248,7 @@ | Property | Limit | |----------|-------| | Item size | 2 MB | -| Tags per Runtime Cache item | 64 | +| Tags per Runtime Cache item | 128 | | Tags per CDN item | 128 | | Max tag length | 256 bytes | | Tags per bulk REST API call | 16 | @@ -242,7 +276,7 @@ ## References -- 📖 docs: https://vercel.com/docs/runtime-cache +- 📖 docs: https://vercel.com/docs/caching/runtime-cache - 📖 changelog: https://vercel.com/changelog/introducing-the-runtime-cache-api - 📖 CLI cache: https://vercel.com/docs/cli/cache -- 📖 CDN cache purging: https://vercel.com/docs/cdn-cache/purge +- 📖 CDN cache purging: https://vercel.com/docs/caching/cdn-cache/purge
Full snapshot data
{
"description": "Vercel Runtime Cache API guidance — ephemeral per-region key-value cache with tag-based invalidation. Shared across Functions, Routing Middleware, and Builds. Use when implementing caching strategies beyond framework-level caching.",
"included_files": [
{
"relative_path": "agents/openai.yaml",
"size_in_bytes": 169
}
],
"name": "runtime-cache",
"skill_md_contents": "---\nname: runtime-cache\ndescription: Vercel Runtime Cache API guidance — ephemeral per-region key-value cache with tag-based invalidation. Shared across Functions, Routing Middleware, and Builds. Use when implementing caching strategies beyond framework-level caching.\nmetadata:\n priority: 6\n docs:\n - \"https://nextjs.org/docs/app/api-reference/directives/use-cache-remote\"\n sitemap: \"https://nextjs.org/sitemap.xml\"\n pathPatterns: \n - 'lib/cache/**'\n - 'src/lib/cache/**'\n - 'lib/cache.*'\n - 'src/lib/cache.*'\n bashPatterns:\n - '\\bnpm\\s+(install|i|add)\\s+[^\\n]*@vercel/functions\\b'\n - '\\bpnpm\\s+(install|i|add)\\s+[^\\n]*@vercel/functions\\b'\n - '\\bbun\\s+(install|i|add)\\s+[^\\n]*@vercel/functions\\b'\n - '\\byarn\\s+add\\s+[^\\n]*@vercel/functions\\b'\nvalidate:\n -\n pattern: 'from\\s+[''\"\"](redis|ioredis)[''\"\"]|require\\s*\\(\\s*[''\"\"](redis|ioredis)[''\"\"]|new\\s+Redis\\('\n message: 'Direct Redis/ioredis client detected. Use Upstash Redis (@upstash/redis) for serverless-native Redis with HTTP-based connections.'\n severity: recommended\n upgradeToSkill: vercel-storage\n upgradeWhy: 'Replace direct Redis/ioredis with @upstash/redis for serverless-compatible HTTP-based Redis that works without persistent TCP connections.'\n skipIfFileContains: 'from\\s+[''\"\"]\\@upstash/redis[''\"\"]'\nretrieval:\n aliases:\n - cache api\n - kv cache\n - region cache\n - tag invalidation\n intents:\n - add caching\n - cache api response\n - invalidate cache\n - set up runtime cache\n entities:\n - Runtime Cache\n - tag-based invalidation\n - key-value\n - cache\nchainTo:\n -\n pattern: 'from\\s+[''\"\"]@vercel/kv[''\"\"]'\n targetSkill: vercel-storage\n message: '@vercel/kv is sunset — loading Vercel Storage guidance for Upstash Redis migration.'\n -\n pattern: 'from\\s+[''\"\"]ioredis[''\"\"]|new\\s+Redis\\('\n targetSkill: vercel-storage\n message: 'Direct Redis client detected — loading Vercel Storage guidance for Upstash Redis (serverless-native) integration.'\n\n---\n\n# Vercel Runtime Cache API\n\nYou are an expert in the Vercel Runtime Cache — an ephemeral caching layer for serverless compute.\n\n## What It Is\n\nThe Runtime Cache is a **per-region key-value store** accessible from Vercel Functions, Routing Middleware, and Builds. It supports **tag-based invalidation** for granular cache control.\n\n- **Regional**: Each Vercel region has its own isolated cache\n- **Isolated**: Scoped per deployment environment (`preview` vs `production`); scoped per project on Pro/Enterprise, but shared across all projects on a Hobby team\n- **Persistent across deployments**: Cached data survives new deploys; invalidation via TTL or `expireTag`\n- **Ephemeral**: Fixed storage limit per project; LRU eviction when full\n- **Framework-agnostic**: Works with any framework via `@vercel/functions`\n\n## Key APIs\n\nAll APIs from `@vercel/functions`:\n\n### Basic Cache Operations\n\n```ts\nimport { getCache } from '@vercel/functions';\n\nconst cache = getCache();\n\n// Store data with TTL and tags\nawait cache.set('user:123', userData, {\n ttl: 3600, // seconds\n tags: ['users', 'user:123'], // for bulk invalidation\n name: 'user-profile', // human-readable label for observability\n});\n\n// Retrieve cached data (returns value or undefined)\nconst data = await cache.get('user:123');\n\n// Delete a specific key\nawait cache.delete('user:123');\n\n// Expire all entries with a tag (propagates globally within 300ms)\nawait cache.expireTag('users');\nawait cache.expireTag(['users', 'user:123']); // multiple tags\n```\n\n### Cache Options\n\n```ts\nconst cache = getCache({\n namespace: 'api', // prefix for keys\n namespaceSeparator: ':', // separator (default)\n keyHashFunction: (key) => sha256(key), // custom key hashing\n});\n```\n\n### Full Example (Framework-Agnostic)\n\n```ts\nimport { getCache } from '@vercel/functions';\n\nexport default {\n async fetch(request: Request) {\n const cache = getCache();\n const cached = await cache.get('blog-posts');\n\n if (cached) {\n return Response.json(cached);\n }\n\n const posts = await fetch('https://api.example.com/posts').then(r => r.json());\n\n await cache.set('blog-posts', posts, {\n ttl: 3600,\n tags: ['blog'],\n });\n\n return Response.json(posts);\n },\n};\n```\n\n### Tag Expiration from Server Action\n\n```ts\n'use server';\nimport { getCache } from '@vercel/functions';\n\nexport async function invalidateBlog() {\n await getCache().expireTag('blog');\n}\n```\n\n## CDN Cache Purging Functions\n\nThese purge across **all three cache layers** (CDN + Runtime Cache + Data Cache):\n\n```ts\nimport { invalidateByTag, dangerouslyDeleteByTag } from '@vercel/functions';\n\n// Stale-while-revalidate: serves stale, revalidates in background\nawait invalidateByTag('blog-posts');\n\n// Hard delete: next request blocks while fetching from origin (cache stampede risk)\nawait dangerouslyDeleteByTag('blog-posts', {\n revalidationDeadlineSeconds: 3600,\n});\n```\n\n**Important distinction**:\n- `cache.expireTag()` — operates on Runtime Cache only\n- `invalidateByTag()` / `dangerouslyDeleteByTag()` — purges CDN + Runtime + Data caches\n\n## Next.js Integration\n\n### Next.js 16+ (`use cache: remote`)\n\n```ts\n// next.config.ts\nconst nextConfig: NextConfig = { cacheComponents: true };\n```\n\n```ts\nimport { cacheLife, cacheTag } from 'next/cache';\n\nasync function getData() {\n 'use cache: remote' // stores in Vercel Runtime Cache\n cacheTag('example-tag')\n cacheLife({ expire: 3600 })\n return fetch('https://api.example.com/data').then(r => r.json());\n}\n```\n\n- `'use cache'` (no `: remote`) — in-memory only, ephemeral per instance\n- `'use cache: remote'` — stores in Vercel Runtime Cache\n\n### Next.js 16 Invalidation APIs\n\n| Function | Context | Behavior |\n|----------|---------|----------|\n| `updateTag(tag)` | Server Actions only | Immediate expiration, read-your-own-writes |\n| `revalidateTag(tag, 'max')` | Server Actions + Route Handlers | Stale-while-revalidate (recommended) |\n| `revalidateTag(tag, { expire: 0 })` | Route Handlers (webhooks) | Immediate expiration from external triggers |\n\n**Important**: Single-argument `revalidateTag(tag)` is deprecated in Next.js 16. Always pass a `cacheLife` profile as the second argument.\n\n### Runtime Cache vs ISR Isolation\n\n- Runtime Cache tags do **NOT** apply to ISR pages\n- `cache.expireTag` does **NOT** invalidate ISR cache\n- Next.js `revalidatePath` / `revalidateTag` does **NOT** invalidate Runtime Cache\n- To manage both, use same tag and purge via `invalidateByTag` (hits all cache layers)\n\n## CLI Cache Commands\n\n```bash\n# Purge all cached data\nvercel cache purge # CDN + Data cache\nvercel cache purge --type cdn # CDN only\nvercel cache purge --type data # Data cache only\nvercel cache purge --yes # skip confirmation\n\n# Invalidate by tag (stale-while-revalidate)\nvercel cache invalidate --tag blog-posts,user-profiles\n\n# Hard delete by tag (blocks until revalidated)\nvercel cache dangerously-delete --tag blog-posts\nvercel cache dangerously-delete --tag blog-posts --revalidation-deadline-seconds 3600\n\n# Image invalidation\nvercel cache invalidate --srcimg /images/hero.jpg\n```\n\nNote: `--tag` and `--srcimg` cannot be used together.\n\n## CDN Cache Tags\n\nAdd tags to CDN cached responses for later invalidation:\n\n```ts\nimport { addCacheTag } from '@vercel/functions';\n\n// Via helper\naddCacheTag('product-123');\n\n// Via response header\nreturn Response.json(product, {\n headers: {\n 'Vercel-CDN-Cache-Control': 'public, max-age=86400',\n 'Vercel-Cache-Tag': 'product-123,products',\n },\n});\n```\n\n## Limits\n\n| Property | Limit |\n|----------|-------|\n| Item size | 2 MB |\n| Tags per Runtime Cache item | 128 |\n| Tags per CDN item | 128 |\n| Max tag length | 256 bytes |\n| Tags per bulk REST API call | 16 |\n\nTags are **case-sensitive** and **cannot contain commas**.\n\n## Observability\n\nMonitor hit rates, invalidation patterns, and storage usage in the Vercel Dashboard under **Observability → Runtime Cache**. The CDN dashboard (March 5, 2026) provides a unified view of global traffic distribution, cache performance metrics, a redesigned purging interface, and **project-level routing** — update response headers or rewrite to external APIs without triggering a new deployment. Project-level routes are available on all plans and take effect instantly.\n\n## When to Use\n\n- Caching API responses or computed data across functions in a region\n- Tag-based invalidation when content changes (CMS webhook → expire tag)\n- Reducing database load for frequently accessed data\n- Cross-function data sharing within a region\n\n## When NOT to Use\n\n- Framework-level page caching → use Next.js Cache Components (`'use cache'`)\n- Persistent storage → use a database (Neon, Upstash)\n- CDN-level full response caching → use `Cache-Control` / `Vercel-CDN-Cache-Control` headers\n- Cross-region shared state → use a database\n- User-specific data that differs per request\n\n## References\n\n- 📖 docs: https://vercel.com/docs/caching/runtime-cache\n- 📖 changelog: https://vercel.com/changelog/introducing-the-runtime-cache-api\n- 📖 CLI cache: https://vercel.com/docs/cli/cache\n- 📖 CDN cache purging: https://vercel.com/docs/caching/cdn-cache/purge\n"
}SHA-256 of public snapshot: 477ade2a3ca78c94b23024f4fcfd374981dbb91ca2ccabe4d449bcaad3a256d0