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.
59
70%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
Fix and improve this skill with Tessl
tessl review fix ./plugins/vercel/skills/runtime-cache/SKILL.mdYou 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 tagsconst 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.jpgNote: --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 headers11c74d6
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.