LogoLaunchSaaS

缓存

为你的应用按需接入 Redis、Upstash 或 Cloudflare KV 缓存

LaunchSaaS 采用拆包设计实现缓存支持。核心包 @launchsaas/cache 定义接口;每个 Provider 是独立的包,按需安装即可。

更新时间: 2026-03-15

架构

@launchsaas/cache               ← 接口 + Cache 服务类(必须)
@launchsaas/cache-redis         ← Redis(TCP,Node.js)
@launchsaas/cache-upstash       ← Upstash Redis(HTTP,Serverless / Edge)
@launchsaas/cache-cloudflare-kv ← Cloudflare KV(HTTP,Cloudflare Workers)

你只需要安装实际使用的 Provider 包,避免引入不需要的 SDK(redis、@upstash/redis、cloudflare),保持构建体积最小。

LaunchSaaS 默认不安装任何 cache provider,因为具体选择取决于你的部署环境。在你自己的应用中,按需安装匹配部署目标的提供商包。

在你的应用中启用缓存

1. 安装 Provider 包

在你的应用目录下,选择 一个 Provider 安装:

# Node.js 服务器(Redis)
pnpm add @launchsaas/cache-redis

# Serverless / Edge / Vercel(Upstash)
pnpm add @launchsaas/cache-upstash

# Cloudflare Workers / Pages
pnpm add @launchsaas/cache-cloudflare-kv

2. 注册环境变量校验

将 Provider 的 keys 导出添加到你应用的 env.ts,确保启动时校验环境变量:

// your-app/src/env.ts
import { createEnv } from "@t3-oss/env-nextjs";

// Redis
import { keys as cacheKeys } from "@launchsaas/cache-redis/keys";

// 或 Upstash
// import { keys as cacheKeys } from "@launchsaas/cache-upstash/keys";

// 或 Cloudflare KV
// import { keys as cacheKeys } from "@launchsaas/cache-cloudflare-kv/keys";

export const env = createEnv({
  extends: [
    cacheKeys,
    // ... 其他 keys
  ],
  // ...
});

3. 配置环境变量

Redis

REDIS_URL=redis://localhost:6379
# 带认证:redis://user:password@host:6379
# 带 TLS: rediss://user:password@host:6379

Upstash Redis

UPSTASH_REDIS_REST_URL=https://your-endpoint.upstash.io
UPSTASH_REDIS_REST_TOKEN=your-rest-token

Cloudflare KV

CLOUDFLARE_ACCOUNT_ID=your-account-id
CLOUDFLARE_KV_NAMESPACE_ID=your-namespace-id
CLOUDFLARE_API_TOKEN=your-api-token

4. 在 src/capabilities.ts 中注册

打开你的应用的 src/capabilities.ts,在 cache 字段中配置缓存 Provider:

// src/capabilities.ts  (你的应用 — apps/launchsaas/src/capabilities.ts)

// Redis
import { RedisCacheProvider } from "@launchsaas/cache-redis";
// Upstash Redis
// import { UpstashRedisCacheProvider } from "@launchsaas/cache-upstash";
// Cloudflare KV
// import { CloudflareKVCacheProvider } from "@launchsaas/cache-cloudflare-kv";

export const capabilities = {
  // 设为 null 即可禁用缓存
  cache: RedisCacheProvider.create(),
  // cache: UpstashRedisCacheProvider.create(),
  // cache: CloudflareKVCacheProvider.create(),
  // ...其他 capabilities
};

启用缓存后的效果

初始化完成后,缓存会被以下功能自动使用:

Better Auth 二级存储

Better Auth 在 src/lib/auth/auth.ts 中读取 capabilities.cache。当其不为 null 时, 会话、API Key 和限流数据将存储在缓存中,而非直接查询数据库:

会话查找:~5-10ms(缓存命中) vs ~50-100ms(数据库查询)

无需额外代码,模板中已经接好了。

自定义缓存

import { capabilities } from "@/capabilities";

// 缓存为可选时,先检查 capabilities.cache 是否存在
const cache = capabilities.cache;
if (cache) {
  await cache.set("my-key", JSON.stringify(data), 3600); // TTL 单位:秒
}

const raw = cache ? await cache.get("my-key") : null;
const data = raw ? JSON.parse(raw) : null;

if (cache) await cache.delete("my-key");

Provider 对比

RedisUpstashCloudflare KV
协议TCPHTTPHTTP
延迟亚毫秒~50-100ms~50-100ms
Edge / Workers
Serverless有限
适合场景传统服务器Vercel / NetlifyCloudflare 部署

Provider 配置指南

Redis — 本地开发

docker run -d -p 6379:6379 redis:7-alpine
# REDIS_URL=redis://localhost:6379

Upstash

  1. console.upstash.com 创建数据库
  2. 从数据库详情页复制 REST URLREST Token
  3. 设置 UPSTASH_REDIS_REST_URLUPSTASH_REDIS_REST_TOKEN

Cloudflare KV

  1. 在 Cloudflare 控制台 Workers & Pages → KV 创建 KV 命名空间
  2. 创建具有 Workers KV Storage: Edit 权限的 API Token
  3. 设置 CLOUDFLARE_ACCOUNT_IDCLOUDFLARE_KV_NAMESPACE_IDCLOUDFLARE_API_TOKEN

自定义 Provider

如果内置 Provider 不满足需求(如 Valkey、Momento、DynamoDB), 正确做法是新建一个 cache-xxx 包,与内置 Provider 包保持相同结构。

1. 新建包

packages/capabilities/cache-xxx/
├── package.json
├── tsconfig.json
└── src/
    ├── keys.ts      ← 环境变量校验(有环境变量时添加)
    ├── provider.ts  ← CacheProvider 实现
    └── index.ts     ← 公开导出

package.json

{
  "name": "@launchsaas/cache-xxx",
  "version": "0.1.0",
  "private": true,
  "main": "./src/index.ts",
  "exports": {
    ".": "./src/index.ts"
  },
  "dependencies": {
    "@launchsaas/cache": "workspace:*",
    "@launchsaas/errors": "workspace:*",
    "server-only": "^0.0.1"
  }
}

src/provider.ts

import "server-only";
import type { CacheProvider } from "@launchsaas/cache";

export class XxxCacheProvider implements CacheProvider {
  readonly name = "xxx";

  async get(key: string): Promise<string | null> {
    // 返回值,找不到则返回 null
  }

  async set(key: string, value: string, ttl?: number): Promise<void> {
    // 存储值;如提供 ttl(单位秒),需按时间过期
  }

  async delete(key: string): Promise<void> {
    // 删除 key
  }

  static create(): XxxCacheProvider {
    // 校验配置 / 初始化客户端
    return new XxxCacheProvider();
  }
}

src/index.ts

export { XxxCacheProvider } from "./provider";
export { keys } from "./keys"; // 无环境变量时可省略

CacheProvider 接口只有三个方法,设计极简。ttl 为可选参数, 后端不支持过期时间时可直接忽略。

2. 添加到你的应用

在应用的 package.json 中添加依赖:

"@launchsaas/cache-xxx": "workspace:*"

如果 Provider 有环境变量,在 src/env.ts 中注册 keys:

import { keys as cacheKeys } from "@launchsaas/cache-xxx";

export const env = createEnv({
  extends: [cacheKeys /* ... */],
});

3. 在 src/capabilities.ts 中注册

// src/capabilities.ts  (apps/launchsaas/src/capabilities.ts)
import { XxxCacheProvider } from "@launchsaas/cache-xxx";

export const capabilities = {
  cache: XxxCacheProvider.create(),
  // ...其他 capabilities
};

常见问题

"Cache not initialized" 报错

capabilities.cache 配置之前就尝试使用缓存。确认 src/capabilities.ts 中的 Provider create() 未抛出错误,且环境变量已正确配置。

Redis 连接被拒绝

TCP 连接是懒加载的(首次使用时才建立)。检查 REDIS_URL 以及 Redis 服务是否可达。 连接错误会以 Redis Client Error: 为前缀输出到 stderr。

Cloudflare KV 404

键不存在时 Provider 会返回 null,这是正常行为。请核实 CLOUDFLARE_KV_NAMESPACE_ID 是否与实际命名空间 ID 一致。