From vercel
Guides Vercel Runtime Cache API for ephemeral per-region KV caching with tag-based invalidation in Functions, Routing Middleware, and Builds. For strategies beyond framework caching.
npx claudepluginhub vercel/vercel-plugin --plugin vercel-pluginThis skill uses the workspace's default tool permissions.
You are an expert in the Vercel Runtime Cache — an ephemeral caching layer for serverless compute.
Guides Netlify CDN caching: Cache-Control headers, stale-while-revalidate, cache tags, on-demand purges, durable cache, vary keys, and Next.js ISR patterns.
Explains Next.js 16 caching layers (Request Memoization, Data Cache, Full Route Cache, Router Cache), 'use cache' directive, fetch options, cacheLife/Tag, revalidation strategies, ISR, and debugging.
Manages Next.js's four cache layers (Data Cache, Full Route Cache, etc.) using fetch options, unstable_cache, revalidatePath, and revalidateTag to control freshness, performance, and invalidation. Use for stale data debugging and API optimization.
Share bugs, ideas, or general feedback.
You are an expert in the Vercel Runtime Cache — an ephemeral caching layer for serverless compute.
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.
preview vs production)expireTag@vercel/functionsAll APIs from @vercel/functions:
import { getCache } from '@vercel/functions';
const cache = getCache();
// Store data with TTL and tags
await cache.set('user:123', userData, {
ttl: 3600, // seconds
tags: ['users', 'user:123'], // for bulk invalidation
name: 'user-profile', // human-readable label for observability
});
// Retrieve cached data (returns value or undefined)
const data = await cache.get('user:123');
// Delete a specific key
await cache.delete('user:123');
// Expire all entries with a tag (propagates globally within 300ms)
await cache.expireTag('users');
await cache.expireTag(['users', 'user:123']); // multiple tags
const cache = getCache({
namespace: 'api', // prefix for keys
namespaceSeparator: ':', // separator (default)
keyHashFunction: (key) => sha256(key), // custom key hashing
});
import { getCache } from '@vercel/functions';
export default {
async fetch(request: Request) {
const cache = getCache();
const cached = await cache.get('blog-posts');
if (cached) {
return Response.json(cached);
}
const posts = await fetch('https://api.example.com/posts').then(r => r.json());
await cache.set('blog-posts', posts, {
ttl: 3600,
tags: ['blog'],
});
return Response.json(posts);
},
};
'use server';
import { getCache } from '@vercel/functions';
export async function invalidateBlog() {
await getCache().expireTag('blog');
}
These purge across all three cache layers (CDN + Runtime Cache + Data Cache):
import { invalidateByTag, dangerouslyDeleteByTag } from '@vercel/functions';
// Stale-while-revalidate: serves stale, revalidates in background
await invalidateByTag('blog-posts');
// Hard delete: next request blocks while fetching from origin (cache stampede risk)
await dangerouslyDeleteByTag('blog-posts', {
revalidationDeadlineSeconds: 3600,
});
Important distinction:
cache.expireTag() — operates on Runtime Cache onlyinvalidateByTag() / dangerouslyDeleteByTag() — purges CDN + Runtime + Data cachesuse cache: remote)// next.config.ts
const nextConfig: NextConfig = { cacheComponents: true };
import { cacheLife, cacheTag } from 'next/cache';
async function getData() {
'use cache: remote' // stores in Vercel Runtime Cache
cacheTag('example-tag')
cacheLife({ expire: 3600 })
return fetch('https://api.example.com/data').then(r => r.json());
}
'use cache' (no : remote) — in-memory only, ephemeral per instance'use cache: remote' — stores in Vercel Runtime Cache| Function | Context | Behavior |
|---|---|---|
updateTag(tag) | Server Actions only | Immediate expiration, read-your-own-writes |
revalidateTag(tag, 'max') | Server Actions + Route Handlers | Stale-while-revalidate (recommended) |
revalidateTag(tag, { expire: 0 }) | Route Handlers (webhooks) | Immediate expiration from external triggers |
Important: Single-argument revalidateTag(tag) is deprecated in Next.js 16. Always pass a cacheLife profile as the second argument.
cache.expireTag does NOT invalidate ISR cacherevalidatePath / revalidateTag does NOT invalidate Runtime CacheinvalidateByTag (hits all cache layers)# Purge all cached data
vercel cache purge # CDN + Data cache
vercel cache purge --type cdn # CDN only
vercel cache purge --type data # Data cache only
vercel cache purge --yes # skip confirmation
# Invalidate by tag (stale-while-revalidate)
vercel cache invalidate --tag blog-posts,user-profiles
# Hard delete by tag (blocks until revalidated)
vercel cache dangerously-delete --tag blog-posts
vercel cache dangerously-delete --tag blog-posts --revalidation-deadline-seconds 3600
# Image invalidation
vercel cache invalidate --srcimg /images/hero.jpg
Note: --tag and --srcimg cannot be used together.
Add tags to CDN cached responses for later invalidation:
import { addCacheTag } from '@vercel/functions';
// Via helper
addCacheTag('product-123');
// Via response header
return Response.json(product, {
headers: {
'Vercel-CDN-Cache-Control': 'public, max-age=86400',
'Vercel-Cache-Tag': 'product-123,products',
},
});
| Property | Limit |
|---|---|
| Item size | 2 MB |
| Tags per Runtime Cache item | 64 |
| Tags per CDN item | 128 |
| Max tag length | 256 bytes |
| Tags per bulk REST API call | 16 |
Tags are case-sensitive and cannot contain commas.
Monitor 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.
'use cache')Cache-Control / Vercel-CDN-Cache-Control headers