Cache Providers
Balda supports three types of cache backends: the built-in in-memory provider, a Redis-backed provider, and any custom provider you implement.
Memory Provider (default)
The MemoryCacheProvider stores entries in a Map inside the current process. It requires no dependencies and is the default when provider is omitted.
import { Server } from "balda";
const server = new Server({
cache: {
provider: "memory",
defaultTtl: 120,
},
});
The memory provider is scoped to a single process. Entries are lost on restart and are not shared across multiple instances. Use Redis for production deployments.
Redis Provider
The RedisCacheProvider uses ioredis as a peer dependency. Install it first:
npm install ioredis
Then configure the server:
import { Server } from "balda";
const server = new Server({
cache: {
provider: "redis",
redis: {
host: "localhost",
port: 6379,
password: "secret",
},
},
});
Redis Connection Options
| Option | Type | Default | Description |
|---|---|---|---|
host | string | 'localhost' | Redis server hostname |
port | number | 6379 | Redis server port |
password | string | — | Redis AUTH password |
db | number | 0 | Redis database index |
keyPrefix | string | — | Prefix for all Redis keys |
url | string | — | Full Redis URL (overrides host/port/password/db) |
Using a Connection URL
const server = new Server({
cache: {
provider: "redis",
redis: {
url: "redis://:password@redis-host:6379/0",
},
},
});
Using a Pre-configured Instance
You can also pass a RedisCacheProvider instance directly, for example to share a connection or configure advanced ioredis options:
import { Server } from "balda";
import { RedisCacheProvider } from "balda/cache";
const redisProvider = new RedisCacheProvider({
host: process.env.REDIS_HOST,
port: Number(process.env.REDIS_PORT),
password: process.env.REDIS_PASSWORD,
keyPrefix: "myapp:",
});
const server = new Server({
cache: { provider: redisProvider },
});
Custom Provider
Implement the CacheProvider interface to use any storage backend (Memcached, DynamoDB, Upstash, etc.).
import type { CacheProvider } from "balda";
class MyCustomProvider implements CacheProvider {
async get(key: string): Promise<string | null> {
/* ... */
}
async set(key: string, value: string, ttlSeconds: number): Promise<void> {
/* ... */
}
async del(key: string): Promise<boolean> {
/* ... */
}
async delMany(keys: string[]): Promise<number> {
/* ... */
}
async addToSet(
key: string,
members: string[],
ttlSeconds?: number,
): Promise<void> {
/* ... */
}
async getSetMembers(key: string): Promise<string[]> {
/* ... */
}
async acquireLock(key: string, ttlMs: number): Promise<boolean> {
/* ... */
}
async releaseLock(key: string): Promise<void> {
/* ... */
}
async *scan(pattern: string): AsyncIterable<string[]> {
/* ... */
}
async disconnect(): Promise<void> {
/* ... */
}
}
const server = new Server({
cache: { provider: new MyCustomProvider() },
});
CacheProvider Interface
| Method | Signature | Description |
|---|---|---|
get | (key) → Promise<string | null> | Fetch a raw string by key |
set | (key, value, ttlSeconds) → Promise<void> | Store with TTL |
del | (key) → Promise<boolean> | Delete one key; returns true if it existed |
delMany | (keys) → Promise<number> | Bulk delete; returns count deleted |
addToSet | (key, members, ttl?) → Promise<void> | Add to a set (used for tag tracking) |
getSetMembers | (key) → Promise<string[]> | Read all set members |
acquireLock | (key, ttlMs) → Promise<boolean> | NX-style lock; true if acquired |
releaseLock | (key) → Promise<void> | Release a lock |
scan | (pattern) → AsyncIterable<string[]> | Cursor-scan by glob pattern |
disconnect | () → Promise<void> | Clean up connections |