LogoLaunchSaaS

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

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

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

Provider Comparison

FeatureRedisUpstash RedisCloudflare KV
ConnectionTCP (persistent)HTTP REST APIHTTP REST API
LatencySub-millisecond~50-100ms~50-100ms
ConsistencyStrongStrongEventually consistent (60s)
Edge SupportNoYesYes (native)
ServerlessLimitedPerfectPerfect
SetupSelf-hosted/managedManagedManaged
CostServer costsPay-per-requestPay-per-request
Best ForTraditional serversServerless/edgeCloudflare 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:6379

AWS ElastiCache

# Get endpoint from AWS Console
REDIS_URL=rediss://your-cluster.cache.amazonaws.com:6379

Azure Cache for Redis

# Get connection string from Azure Portal
REDIS_URL=rediss://your-cache.redis.cache.windows.net:6380

Upstash Redis Setup

  1. Create Database at console.upstash.com
  2. Copy REST credentials from database details
  3. Configure environment:
UPSTASH_REDIS_REST_URL=https://your-endpoint.upstash.io
UPSTASH_REDIS_REST_TOKEN=your-rest-token
  1. 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

  1. Create KV Namespace in Cloudflare Dashboard
  2. Create API Token with KV permissions
  3. Configure environment:
CLOUDFLARE_ACCOUNT_ID=abc123
CLOUDFLARE_KV_NAMESPACE_ID=xyz789
CLOUDFLARE_API_TOKEN=your-token

Architecture

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 hours

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

  1. Choose provider based on your infrastructure:
    • Traditional server → redis
    • Serverless/edge → upstash
    • Cloudflare → cloudflare-kv
  2. Set up cache instance (Redis/Upstash/Cloudflare KV)
  3. Configure environment variables
  4. Enable in features:
    cache: {
      provider: "redis";
    } // or "upstash" or "cloudflare-kv"
  5. Restart application
  6. Verify logs show cache initialization
  7. Monitor session performance improvements

Switching Providers

No data migration needed - cache is ephemeral:

  1. Update features.ts with new provider
  2. Set new environment variables
  3. Remove old environment variables
  4. Restart application

Old cache data is automatically discarded.

References

Next Steps