Cache Module
The cache module (src/lib/core/cache/) provides a provider-based caching layer with no silent fallbacks. The active provider is selected via the CACHE_PROVIDER environment variable.
Why
- Provider abstraction — Swap between no-cache, in-memory, and Redis without changing application code.
- No silent fallback — If Redis is configured and unavailable, operations fail explicitly instead of silently degrading.
- TTL support — Default and per-key TTL for automatic expiration.
- Singleton lifecycle — Initialized once, destroyed on graceful shutdown.
Providers
| Provider | CACHE_PROVIDER | Description |
|---|---|---|
| Null | none | Caching disabled — all reads miss, writes are no-ops |
| Memory | memory | In-process Map with TTL sweep (default) |
| Redis | redis | Redis via ioredis — requires REDIS_URL |
Usage
typescript
import { getCache } from '@/lib/core/cache';
const cache = await getCache();
// Set with default TTL (CACHE_TTL_SECONDS)
await cache.set('user:123', { name: 'Alice', role: 'admin' });
// Set with custom TTL (seconds)
await cache.set('session:abc', sessionData, 3600);
// Get (returns undefined on miss)
const user = await cache.get<User>('user:123');
if (user) {
// cache hit
}
// Check existence
const exists = await cache.has('user:123');
// Delete
await cache.del('user:123');
// Clear all (use with caution)
await cache.clear();API Reference
getCache(): Promise<CacheProvider>
Returns the initialized cache provider singleton. First call triggers initialization.
destroyCache(): Promise<void>
Destroys the cache provider. Called during graceful shutdown.
CacheProvider Interface
typescript
interface CacheProvider {
readonly name: string;
init(): Promise<void>;
get<T = unknown>(key: string): Promise<T | undefined>;
set<T = unknown>(key: string, value: T, ttlSeconds?: number): Promise<void>;
del(key: string): Promise<void>;
has(key: string): Promise<boolean>;
clear(): Promise<void>;
destroy(): Promise<void>;
}Configuration
| Variable | Default | Description |
|---|---|---|
CACHE_PROVIDER | memory | Provider: none, memory, redis |
CACHE_TTL_SECONDS | 300 | Default TTL for cached entries |
REDIS_URL | — | Redis connection URL (required for redis provider) |
REDIS_KEY_PREFIX | console: | Key prefix for Redis entries |
Where Cache is Used
The gateway uses caching in these critical paths:
| Use Case | Key Pattern | TTL |
|---|---|---|
| API token validation | apiToken:{hash} | 300s |
| Model metadata lookup | model:{tenantDb}:{key} | 300s |
| Provider config | provider:{tenantDb}:{key} | 300s |
Health Check
The cache module registers a health check that verifies the provider can read and write:
typescript
registerHealthCheck('cache', async () => {
const cache = await getCache();
await cache.set('__health__', 'ok', 10);
const val = await cache.get('__health__');
return {
status: val === 'ok' ? 'ok' : 'degraded',
details: { provider: cache.name },
};
});Shutdown
Cache is destroyed during graceful shutdown:
typescript
registerShutdownHandler('cache', async () => {
await destroyCache();
});Rules
Mandatory: Access cache only through
getCache()from@/lib/core/cache. The provider is selected byCACHE_PROVIDERenv var. No silent fallback: if Redis is configured and unavailable, operations fail explicitly.