runtime-cache

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Vercel 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 (
    preview
    vs
    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/functions

Basic 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 tags
ts
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:
  • cache.expireTag()
    — operates on Runtime Cache only
  • invalidateByTag()
    /
    dangerouslyDeleteByTag()
    — purges CDN + Runtime + Data caches
这些函数会清理全部三层缓存(CDN + Runtime Cache + 数据缓存):
ts
import { invalidateByTag, dangerouslyDeleteByTag } from '@vercel/functions';

// 失效时返回旧值并在后台重新验证:返回过期内容,后台重新获取最新值
await invalidateByTag('blog-posts');

// 硬删除:下一次请求会阻塞,直到从源站获取数据(存在缓存击穿风险)
await dangerouslyDeleteByTag('blog-posts', {
  revalidationDeadlineSeconds: 3600,
});
关键区别
  • cache.expireTag()
    — 仅作用于Runtime Cache
  • invalidateByTag()
    /
    dangerouslyDeleteByTag()
    — 清理CDN + Runtime + 数据缓存

Next.js Integration

Next.js 集成

Next.js 16+ (
use cache: remote
)

Next.js 16+(
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'     // 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
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
    )— 仅内存存储,每个实例临时有效
  • 'use cache: remote'
    — 存储到Vercel Runtime Cache

Next.js 16 Invalidation APIs

Next.js 16 失效API

FunctionContextBehavior
updateTag(tag)
Server Actions onlyImmediate expiration, read-your-own-writes
revalidateTag(tag, 'max')
Server Actions + Route HandlersStale-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.
函数上下文行为
updateTag(tag)
仅Server Actions立即失效,读写一致
revalidateTag(tag, 'max')
Server Actions + 路由处理器返回旧值并后台重新验证(推荐)
revalidateTag(tag, { expire: 0 })
路由处理器(Webhook)从外部触发立即失效
重要提示:单参数
revalidateTag(tag)
在Next.js 16中已弃用。请始终传入
cacheLife
配置作为第二个参数。

Runtime Cache vs ISR Isolation

Runtime Cache 与 ISR 的隔离性

  • Runtime Cache tags do NOT apply to ISR pages
  • cache.expireTag
    does NOT invalidate ISR cache
  • Next.js
    revalidatePath
    /
    revalidateTag
    does NOT invalidate Runtime Cache
  • To manage both, use same tag and purge via
    invalidateByTag
    (hits all cache layers)
  • Runtime Cache的标签不适用于ISR页面
  • cache.expireTag
    不会使ISR缓存失效
  • Next.js的
    revalidatePath
    /
    revalidateTag
    不会使Runtime Cache失效
  • 如需同时管理两者,请使用相同标签并通过
    invalidateByTag
    清理(会作用于所有缓存层)

CLI Cache Commands

CLI 缓存命令

bash
undefined
bash
undefined

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
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

限制

PropertyLimit
Item size2 MB
Tags per Runtime Cache item64
Tags per CDN item128
Max tag length256 bytes
Tags per bulk REST API call16
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-Control
    /
    Vercel-CDN-Cache-Control
    headers
  • 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

参考资料