runtime-cache
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseVercel Runtime Cache API
Vercel Runtime Cache API
You are an expert in the Vercel Runtime Cache — an ephemeral caching layer for serverless compute.
您是Vercel Runtime Cache的专家——这是一款面向无服务器计算的临时缓存层。
What It Is
是什么
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 (vs
preview)production - 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
Runtime Cache是一个区域级键值存储,可从Vercel Functions、路由中间件和构建流程中访问。它支持基于标签的失效机制,实现精细化缓存控制。
- 区域化:每个Vercel区域都有独立的缓存
- 隔离性:按项目和部署环境(与
preview)划分作用域production - 跨部署持久化:缓存数据可在新部署后保留;可通过TTL或进行失效
expireTag - 临时性:每个项目有固定存储限制;存储空间满时采用LRU淘汰机制
- 框架无关:可通过与任意框架配合使用
@vercel/functions
Key APIs
核心API
All APIs from :
@vercel/functions所有API均来自:
@vercel/functionsBasic Cache Operations
基础缓存操作
ts
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 tagsts
import { getCache } from '@vercel/functions';
const cache = getCache();
// 存储带TTL和标签的数据
await cache.set('user:123', userData, {
ttl: 3600, // 秒
tags: ['users', 'user:123'], // 用于批量失效
name: 'user-profile', // 用于可观测性的可读标签
});
// 获取缓存数据(返回值或undefined)
const data = await cache.get('user:123');
// 删除指定键
await cache.delete('user:123');
// 使所有带指定标签的条目失效(300ms内全局生效)
await cache.expireTag('users');
await cache.expireTag(['users', 'user:123']); // 多个标签Cache Options
缓存配置选项
ts
const cache = getCache({
namespace: 'api', // prefix for keys
namespaceSeparator: ':', // separator (default)
keyHashFunction: (key) => sha256(key), // custom key hashing
});ts
const cache = getCache({
namespace: 'api', // 键的前缀
namespaceSeparator: ':', // 分隔符(默认值)
keyHashFunction: (key) => sha256(key), // 自定义键哈希函数
});Full Example (Framework-Agnostic)
完整示例(框架无关)
ts
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);
},
};ts
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);
},
};Tag Expiration from Server Action
从Server Action触发标签失效
ts
'use server';
import { getCache } from '@vercel/functions';
export async function invalidateBlog() {
await getCache().expireTag('blog');
}ts
'use server';
import { getCache } from '@vercel/functions';
export async function invalidateBlog() {
await getCache().expireTag('blog');
}CDN Cache Purging Functions
CDN缓存清理函数
These purge across all three cache layers (CDN + Runtime Cache + Data Cache):
ts
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:
- — operates on Runtime Cache only
cache.expireTag() - /
invalidateByTag()— purges CDN + Runtime + Data cachesdangerouslyDeleteByTag()
这些函数会清理全部三层缓存(CDN + Runtime Cache + 数据缓存):
ts
import { invalidateByTag, dangerouslyDeleteByTag } from '@vercel/functions';
// 失效时返回旧值并在后台重新验证:返回过期内容,后台重新获取最新值
await invalidateByTag('blog-posts');
// 硬删除:下一次请求会阻塞,直到从源站获取数据(存在缓存击穿风险)
await dangerouslyDeleteByTag('blog-posts', {
revalidationDeadlineSeconds: 3600,
});关键区别:
- — 仅作用于Runtime Cache
cache.expireTag() - /
invalidateByTag()— 清理CDN + Runtime + 数据缓存dangerouslyDeleteByTag()
Next.js Integration
Next.js 集成
Next.js 16+ (use cache: remote
)
use cache: remoteNext.js 16+(use cache: remote
)
use cache: remotets
// next.config.ts
const nextConfig: NextConfig = { cacheComponents: true };ts
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());
}- (no
'use cache') — in-memory only, ephemeral per instance: remote - — stores in Vercel Runtime Cache
'use cache: remote'
ts
// next.config.ts
const nextConfig: NextConfig = { cacheComponents: true };ts
import { cacheLife, cacheTag } from 'next/cache';
async function getData() {
'use cache: remote' // 存储到Vercel Runtime Cache
cacheTag('example-tag')
cacheLife({ expire: 3600 })
return fetch('https://api.example.com/data').then(r => r.json());
}- (不带
'use cache')— 仅内存存储,每个实例临时有效: remote - — 存储到Vercel Runtime Cache
'use cache: remote'
Next.js 16 Invalidation APIs
Next.js 16 失效API
| Function | Context | Behavior |
|---|---|---|
| Server Actions only | Immediate expiration, read-your-own-writes |
| Server Actions + Route Handlers | Stale-while-revalidate (recommended) |
| Route Handlers (webhooks) | Immediate expiration from external triggers |
Important: Single-argument is deprecated in Next.js 16. Always pass a profile as the second argument.
revalidateTag(tag)cacheLife| 函数 | 上下文 | 行为 |
|---|---|---|
| 仅Server Actions | 立即失效,读写一致 |
| Server Actions + 路由处理器 | 返回旧值并后台重新验证(推荐) |
| 路由处理器(Webhook) | 从外部触发立即失效 |
重要提示:单参数在Next.js 16中已弃用。请始终传入配置作为第二个参数。
revalidateTag(tag)cacheLifeRuntime Cache vs ISR Isolation
Runtime Cache 与 ISR 的隔离性
- Runtime Cache tags do NOT apply to ISR pages
- does NOT invalidate ISR cache
cache.expireTag - Next.js /
revalidatePathdoes NOT invalidate Runtime CacherevalidateTag - To manage both, use same tag and purge via (hits all cache layers)
invalidateByTag
- Runtime Cache的标签不适用于ISR页面
- 不会使ISR缓存失效
cache.expireTag - Next.js的/
revalidatePath不会使Runtime Cache失效revalidateTag - 如需同时管理两者,请使用相同标签并通过清理(会作用于所有缓存层)
invalidateByTag
CLI Cache Commands
CLI 缓存命令
bash
undefinedbash
undefinedPurge 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
vercel cache purge # CDN + 数据缓存
vercel cache purge --type cdn # 仅CDN
vercel cache purge --type data # 仅数据缓存
vercel cache purge --yes # 跳过确认
Invalidate by tag (stale-while-revalidate)
按标签失效(返回旧值并后台重新验证)
vercel cache invalidate --tag blog-posts,user-profiles
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
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.vercel cache invalidate --srcimg /images/hero.jpg
注意:`--tag` 和 `--srcimg` 不能同时使用。CDN Cache Tags
CDN 缓存标签
Add tags to CDN cached responses for later invalidation:
ts
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',
},
});可为CDN缓存响应添加标签,以便后续失效:
ts
import { addCacheTag } from '@vercel/functions';
// 通过工具函数添加
addCacheTag('product-123');
// 通过响应头添加
return Response.json(product, {
headers: {
'Vercel-CDN-Cache-Control': 'public, max-age=86400',
'Vercel-Cache-Tag': 'product-123,products',
},
});Limits
限制
| 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.
| 属性 | 限制 |
|---|---|
| 条目大小 | 2 MB |
| 每个Runtime Cache条目的标签数量 | 64 |
| 每个CDN条目的标签数量 | 128 |
| 标签最大长度 | 256字节 |
| 批量REST API调用的标签数量 | 16 |
标签区分大小写且不能包含逗号。
Observability
可观测性
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.
可在Vercel控制台的可观测性 → Runtime Cache页面监控缓存命中率、失效模式和存储使用情况。CDN控制台(2026年3月5日更新)提供全局流量分布、缓存性能指标的统一视图,以及重新设计的清理界面和项目级路由功能——无需触发新部署即可更新响应头或重写到外部API。项目级路由对所有套餐开放,且立即生效。
When to Use
适用场景
- Caching API responses or computed data across functions in a region
- Tag-based invalidation when content changes (CMS webhook → expire tag)
- Reducing database load for frequently accessed data
- Cross-function data sharing within a region
- 在同一区域的多个函数之间缓存API响应或计算数据
- 内容变更时(如CMS Webhook触发)使用基于标签的失效机制
- 减少高频访问数据对数据库的压力
- 同一区域内跨函数共享数据
When NOT to Use
不适用场景
- Framework-level page caching → use Next.js Cache Components ()
'use cache' - Persistent storage → use a database (Neon, Upstash)
- CDN-level full response caching → use /
Cache-ControlheadersVercel-CDN-Cache-Control - Cross-region shared state → use a database
- User-specific data that differs per request
- 框架级页面缓存 → 使用Next.js Cache Components()
'use cache' - 持久化存储 → 使用数据库(如Neon、Upstash)
- CDN级全响应缓存 → 使用/
Cache-Control响应头Vercel-CDN-Cache-Control - 跨区域共享状态 → 使用数据库
- 每个请求都不同的用户特定数据
References
参考资料
- 📖 docs: https://vercel.com/docs/infrastructure/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