Cache
Add cache support to your app using Redis, Upstash, or Cloudflare KV
LaunchSaaS provides cache support via a split-package design. The core @launchsaas/cache package defines the interface and Cache service; each provider is a separate package that you install only when needed.
Updated: 2026-03-15
Architecture
@launchsaas/cache ← interface + Cache class (always needed)
@launchsaas/cache-redis ← Redis (TCP, Node.js)
@launchsaas/cache-upstash ← Upstash Redis (HTTP, serverless / edge)
@launchsaas/cache-cloudflare-kv ← Cloudflare KV (HTTP, Cloudflare Workers)You only add the provider package you actually use. This keeps your bundle lean and avoids pulling in SDKs (redis, @upstash/redis, cloudflare) you don't need.
LaunchSaaS ships with no cache provider installed by default — the right choice depends on your deployment target. In your own app, install whichever provider matches your infrastructure.
Adding Cache to Your App
1. Install the provider package
In your app directory pick one provider and install it:
# Node.js server (Redis)
pnpm add @launchsaas/cache-redis
# Serverless / Edge / Vercel (Upstash)
pnpm add @launchsaas/cache-upstash
# Cloudflare Workers / Pages
pnpm add @launchsaas/cache-cloudflare-kv2. Add env variables
Add the provider's keys export to your app's env.ts so the env vars are
validated at startup.
// your-app/src/env.ts
import { createEnv } from "@t3-oss/env-nextjs";
// Redis
import { keys as cacheKeys } from "@launchsaas/cache-redis/keys";
// or Upstash
// import { keys as cacheKeys } from "@launchsaas/cache-upstash/keys";
// or Cloudflare KV
// import { keys as cacheKeys } from "@launchsaas/cache-cloudflare-kv/keys";
export const env = createEnv({
extends: [
cacheKeys,
// ... other keys
],
// ...
});3. Set environment variables
Redis
REDIS_URL=redis://localhost:6379
# With auth: redis://user:password@host:6379
# With TLS: rediss://user:password@host:6379Upstash Redis
UPSTASH_REDIS_REST_URL=https://your-endpoint.upstash.io
UPSTASH_REDIS_REST_TOKEN=your-rest-tokenCloudflare KV
CLOUDFLARE_ACCOUNT_ID=your-account-id
CLOUDFLARE_KV_NAMESPACE_ID=your-namespace-id
CLOUDFLARE_API_TOKEN=your-api-token4. Register in src/capabilities.ts
Open your app's src/capabilities.ts and configure the cache provider in the cache field:
// src/capabilities.ts (your app — apps/launchsaas/src/capabilities.ts)
// Redis (Node.js TCP)
import { RedisCacheProvider } from "@launchsaas/cache-redis";
// Upstash Redis (HTTP / serverless)
// import { UpstashRedisCacheProvider } from "@launchsaas/cache-upstash";
// Cloudflare KV
// import { CloudflareKVCacheProvider } from "@launchsaas/cache-cloudflare-kv";
export const capabilities = {
// set to null to disable cache
cache: RedisCacheProvider.create(),
// cache: UpstashRedisCacheProvider.create(),
// cache: CloudflareKVCacheProvider.create(),
// ...other capabilities
};What Cache Unlocks
Once initialized, cache is used automatically by:
Better Auth Secondary Storage
Better Auth reads capabilities.cache in src/lib/auth/auth.ts. When non-null, sessions,
API keys, and rate-limit data are stored in cache instead of the database:
Session lookup: ~5-10ms (cache hit) vs ~50-100ms (DB query)No extra code needed — it's already wired in the template.
Custom Caching
import { capabilities } from "@/capabilities";
const { cache } = capabilities;
// Guard: only use cache if configured
if (cache) {
await cache.set("my-key", JSON.stringify(data), 3600); // TTL in seconds
}
const raw = (await cache?.get("my-key")) ?? null;
const data = raw ? JSON.parse(raw) : null;
await cache?.delete("my-key");Provider Comparison
| Redis | Upstash | Cloudflare KV | |
|---|---|---|---|
| Protocol | TCP | HTTP | HTTP |
| Latency | sub-ms | ~50-100 ms | ~50-100 ms |
| Edge / Workers | ✗ | ✓ | ✓ |
| Serverless | Limited | ✓ | ✓ |
| Best for | Traditional servers | Vercel / Netlify | Cloudflare deployments |
Provider Setup Guides
Redis — Local Dev
docker run -d -p 6379:6379 redis:7-alpine
# REDIS_URL=redis://localhost:6379Upstash
- Create a database at console.upstash.com
- Copy the REST URL and REST Token from the database details page
- Set
UPSTASH_REDIS_REST_URLandUPSTASH_REDIS_REST_TOKEN
Cloudflare KV
- Create a KV namespace in the Cloudflare Dashboard → Workers & Pages → KV
- Create an API token with Workers KV Storage: Edit permission
- Set
CLOUDFLARE_ACCOUNT_ID,CLOUDFLARE_KV_NAMESPACE_ID,CLOUDFLARE_API_TOKEN
Custom Provider
If none of the built-in providers fit your needs (e.g. Valkey, Momento, DynamoDB), create a new package following the same structure as the built-in ones.
1. Create the package
packages/cache-xxx/
├── package.json
├── tsconfig.json
└── src/
├── keys.ts ← env var validation (if needed)
├── provider.ts ← CacheProvider implementation
└── index.ts ← public exportspackage.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> {
// return the value, or null if not found
}
async set(key: string, value: string, ttl?: number): Promise<void> {
// store value; honour ttl (seconds) when provided
}
async delete(key: string): Promise<void> {
// remove the key
}
static create(): XxxCacheProvider {
// validate config / instantiate client
return new XxxCacheProvider();
}
}src/index.ts
export { XxxCacheProvider } from "./provider";
export { keys } from "./keys"; // omit if no env vars neededThe CacheProvider interface only requires three methods. ttl is optional;
ignore it if your backend doesn't support expiry.
2. Add it to your app
In your app's package.json:
"@launchsaas/cache-xxx": "workspace:*"If the provider has env vars, register its keys in src/env.ts:
import { keys as cacheKeys } from "@launchsaas/cache-xxx";
export const env = createEnv({
extends: [cacheKeys /* ... */],
});3. Register in capabilities.ts
// src/capabilities.ts (apps/launchsaas/src/capabilities.ts)
import { XxxCacheProvider } from "@launchsaas/cache-xxx";
export const capabilities = {
cache: XxxCacheProvider.create(),
// ...other capabilities
};Troubleshooting
"Cache not configured" error
capabilities.cache is null in capabilities.ts. Install a provider package and set it to a provider instance.
Redis connection refused
The TCP connection happens on first use (lazy). Check REDIS_URL and that your
Redis server is reachable. Connection errors are logged to stderr with the prefix
Redis Client Error:.
Cloudflare KV 404
Normal for keys that don't exist — the provider returns null. Verify
CLOUDFLARE_KV_NAMESPACE_ID matches your actual namespace ID.