Cache Configuration
Configure cache providers for Better Auth and application caching
Cache Configuration
LaunchSaaS supports multiple cache providers for Better Auth secondary storage and general application caching. Cache improves performance by reducing database queries for frequently accessed data like sessions and API keys.
Updated: 2026-01-13
Overview
The cache system provides:
- Better Auth Integration - Automatic session caching
- Multiple Providers - Redis, Upstash Redis, Cloudflare KV
- Factory Pattern - Easy provider switching
- Type Safety - Full TypeScript support
- Graceful Degradation - Falls back to database if cache unavailable
Configuration
1. Enable Cache Provider
Edit src/configuration/features.ts:
const local: Features = {
// ... other features
cache: {
provider: "redis", // "redis" | "cloudflare-kv" | "disabled"
},
};2. Environment Variables
Standard Redis
For local Redis or managed Redis services (AWS ElastiCache, Azure Cache for Redis, etc.):
# Standard Redis connection
REDIS_URL=redis://localhost:6379
# With authentication
REDIS_URL=redis://username:password@host:6379
# With TLS
REDIS_URL=rediss://username:password@host:6379Upstash Redis (REST API)
For Upstash Redis using HTTP REST API:
# Upstash Redis REST endpoint
REDIS_REST_URL=https://your-endpoint.upstash.io
REDIS_REST_TOKEN=your-rest-tokenWhen both REDIS_URL and REDIS_REST_URL are present, REST API takes
precedence for better edge compatibility.
Cloudflare KV
For Cloudflare KV storage:
CLOUDFLARE_ACCOUNT_ID=your-account-id
CLOUDFLARE_KV_NAMESPACE_ID=your-namespace-id
CLOUDFLARE_API_TOKEN=your-api-tokenProvider Comparison
| Feature | Redis | Upstash Redis | Cloudflare KV |
|---|---|---|---|
| Connection | TCP (persistent) | HTTP REST API | HTTP REST API |
| Latency | Sub-millisecond | ~50-100ms | ~50-100ms |
| Consistency | Strong | Strong | Eventually consistent (60s) |
| Edge Support | No | Yes | Yes (native) |
| Serverless | Limited | Perfect | Perfect |
| Setup | Self-hosted/managed | Managed | Managed |
| Cost | Server costs | Pay-per-request | Pay-per-request |
| Best For | Traditional servers | Serverless/edge | Cloudflare deployments |
Use Cases
Better Auth Secondary Storage
When cache is enabled, Better Auth automatically stores:
- Session data - Faster session lookups without database queries
- API keys - Quick API key validation
- Rate limiting - Efficient rate limit tracking
No additional code needed - Better Auth handles this automatically.
Custom Caching
Use the cache provider directly in your code:
import { getCacheProvider } from "@/lib/cache";
const cache = getCacheProvider();
// Set with TTL (in seconds)
await cache.set("user-settings:123", JSON.stringify(settings), 3600);
// Get value
const cached = await cache.get("user-settings:123");
const settings = cached ? JSON.parse(cached) : null;
// Delete
await cache.delete("user-settings:123");Provider Setup Guides
Redis Setup
Local Development
# Using Docker
docker run -d -p 6379:6379 redis:7-alpine
# Configure
REDIS_URL=redis://localhost:6379AWS ElastiCache
# Get endpoint from AWS Console
REDIS_URL=rediss://your-cluster.cache.amazonaws.com:6379Azure Cache for Redis
# Get connection string from Azure Portal
REDIS_URL=rediss://your-cache.redis.cache.windows.net:6380Upstash Redis Setup
- Create Database at console.upstash.com
- Copy REST credentials from database details
- Configure environment:
UPSTASH_REDIS_REST_URL=https://your-endpoint.upstash.io
UPSTASH_REDIS_REST_TOKEN=your-rest-token- Enable in features.ts:
cache: {
provider: "upstash";
}Upstash Redis is perfect for serverless deployments (Vercel, Netlify, Cloudflare Workers) as it uses HTTP instead of persistent TCP connections.
Cloudflare KV Setup
- Create KV Namespace in Cloudflare Dashboard
- Create API Token with KV permissions
- Configure environment:
CLOUDFLARE_ACCOUNT_ID=abc123
CLOUDFLARE_KV_NAMESPACE_ID=xyz789
CLOUDFLARE_API_TOKEN=your-tokenArchitecture
Provider Interface
All cache providers implement the CacheProvider interface:
interface CacheProvider {
get(key: string): Promise<string | null>;
set(key: string, value: string, ttl?: number): Promise<void>;
delete(key: string): Promise<void>;
isConnected(): Promise<boolean>;
disconnect(): Promise<void>;
}Factory Pattern
The cache factory manages provider initialization:
// Automatically initialized in src/instrumentation.ts
await CacheProviderFactory.initializeProvider();
// Get singleton instance
const cache = CacheProviderFactory.getProvider();Better Auth Integration
Better Auth uses cache as secondary storage (configured in src/lib/auth/auth.ts):
export const auth = betterAuth({
// ... other config
secondaryStorage: getSecondaryStorage(),
});Performance Benefits
With Cache Enabled
Session lookup: ~5-10ms (cache hit)
API key validation: ~5-10ms (cache hit)
Rate limit check: ~5-10ms (cache hit)Without Cache
Session lookup: ~50-100ms (database query)
API key validation: ~50-100ms (database query)
Rate limit check: ~50-100ms (database query)Result: 5-10x faster authentication operations
Troubleshooting
Cache Not Connecting
Check instrumentation logs:
# Start dev server
pnpm dev
# Look for cache initialization logs
# ✓ Cache provider redis initialized successfully
# ✗ Failed to initialize cache provider: [error]Upstash Connection Issues
Verify REST credentials:
// Test connection
const response = await fetch(`${process.env.REDIS_REST_URL}/get/test-key`, {
headers: {
Authorization: `Bearer ${process.env.REDIS_REST_TOKEN}`,
},
});Cloudflare KV Issues
Check API token permissions:
- Worker Scripts: Read
- Workers KV Storage: Read & Write
Cache Bypass
Disable cache temporarily:
// In src/configuration/features.ts
cache: {
provider: "disabled",
}Application will work normally using database only.
Best Practices
1. TTL Strategy
Set appropriate TTLs based on data volatility:
// Short TTL for frequently changing data
await cache.set("online-users", data, 60); // 1 minute
// Medium TTL for user sessions
await cache.set("session:xyz", session, 3600); // 1 hour
// Long TTL for rarely changing data
await cache.set("app-config", config, 86400); // 24 hours2. Cache Keys
Use consistent, hierarchical naming:
// Good
"user:123:settings";
"session:abc-def-123";
"rate-limit:api:192.168.1.1";
// Avoid
"userSettings123";
"sess_abc";
"rl_192.168.1.1";3. Error Handling
Always handle cache failures gracefully:
try {
const cached = await cache.get(key);
if (cached) return JSON.parse(cached);
} catch (error) {
console.error("Cache error:", error);
// Fall back to database
}4. Cache Invalidation
Invalidate cache when data changes:
// After updating user
await updateUser(userId, data);
await cache.delete(`user:${userId}:settings`);Production Checklist
- Choose appropriate cache provider for your infrastructure
- Set up production cache instance (Redis/Upstash/Cloudflare KV)
- Configure environment variables in production
- Enable monitoring/alerting for cache service
- Test cache failover (disable cache, verify app still works)
- Document cache key patterns for your team
- Set up cache metrics dashboard (optional)
Migration Guide
From No Cache to Redis
- Choose provider based on your infrastructure:
- Traditional server →
redis - Serverless/edge →
upstash - Cloudflare →
cloudflare-kv
- Traditional server →
- Set up cache instance (Redis/Upstash/Cloudflare KV)
- Configure environment variables
- Enable in features:
cache: { provider: "redis"; } // or "upstash" or "cloudflare-kv" - Restart application
- Verify logs show cache initialization
- Monitor session performance improvements
Switching Providers
No data migration needed - cache is ephemeral:
- Update features.ts with new provider
- Set new environment variables
- Remove old environment variables
- Restart application
Old cache data is automatically discarded.
References
- Better Auth Secondary Storage
- Redis Documentation
- Upstash Documentation
- Cloudflare KV Documentation
- Features Configuration
- Environment Variables