Object caching for Node.js. Wraps async functions and caches results with automatic key generation.
- LRU in-memory cache with TTL support
- Optional Redis backend for distributed caching
- Request deduplication (prevents thundering herd)
- Promise and callback APIs
- TypeScript definitions included
npm install obcachejsRequires Node.js 18+
const obcache = require('obcachejs');
const cache = new obcache.Create({ max: 1000, maxAge: 60000 });
const getUser = cache.wrap(function(id, callback) {
// Simulate async database lookup
setTimeout(() => callback(null, { id, name: 'User ' + id }), 10);
});
// Promise style
const user = await getUser(123);
console.log(user); // { id: 123, name: 'User 123' }
// Callback style
getUser(456, (err, user) => console.log(user));Creates a cache instance.
const cache = new obcache.Create({
max: 1000, // max keys (default: 1000)
maxAge: 60000, // TTL in ms
queueEnabled: true // deduplicate concurrent requests
});Options:
| Option | Description |
|---|---|
max |
Maximum number of cached keys |
maxSize |
Maximum cache size in bytes (alternative to max) |
maxAge |
Time-to-live in milliseconds |
queueEnabled |
Enable request deduplication |
dispose |
Function called when entries are evicted |
reset.interval |
Auto-reset interval in ms |
reset.firstReset |
First reset time (Date or ms) |
Wraps a callback-based function with caching. The wrapped function:
- Returns a Promise when called without a callback
- Calls the callback when provided as last argument
- Generates cache keys from function name and arguments
const cached = cache.wrap(myAsyncFn);
// Exclude arguments from key generation
const cached = cache.wrap(function(id, timestamp, cb) {
// timestamp won't affect cache key
cb(null, result);
}, null, [1]);Pre-populate cache for given arguments.
cache.warmup(getUser, 123, { id: 123, name: 'Alice' });Remove cached entry for given arguments.
cache.invalidate(getUser, 123);Returns true when cache backend is ready. Always true for LRU, waits for connection with Redis.
Cache statistics object.
{
hit: 0, // cache hits
miss: 0, // cache misses
reset: 0, // number of resets
pending: 0 // queued requests
}const cache = new obcache.Create({
max: 10000,
maxAge: 300000,
id: 1, // required for Redis
redis: {
host: 'localhost',
port: 6379,
connectTimeout: 5000
}
});
// Wait for connection
if (!cache.isReady()) {
// handle not ready
}Redis options:
| Option | Description |
|---|---|
host |
Redis host |
port |
Redis port |
url |
Connection URL (alternative to host/port) |
database |
Redis database number |
connectTimeout |
Connection timeout in ms (default: 5000) |
twemproxy |
Enable twemproxy compatibility |
Register caches for inspection:
obcache.debug.register(cache, 'users');
// Express middleware
app.get('/debug/cache', obcache.debug.view);
// Console output
obcache.debug.log();Security Warning: The debug endpoint exposes cached data via ?detail=cachename and allows cache flushing via POST with ?flush=cachename. Never expose this endpoint publicly. Always protect it with authentication middleware:
app.get('/debug/cache', requireAdmin, obcache.debug.view);obcachejs generates cache keys by hashing the function name and serialized arguments using sigmund. When a wrapped function is called:
- Generate key from function name + arguments
- Check cache for existing value
- On hit: return cached value
- On miss: call original function, cache result, return
With queueEnabled, concurrent calls with the same key are queued and resolved together, preventing duplicate work.
Type definitions are included.
const obcache = require('obcachejs');
// or with ES modules: import obcache from 'obcachejs';
const cache = new obcache.Create({ max: 100 });Types available: Cache, CacheOptions, CacheStats, CachedFunction.
- Redis authentication: Use the
urloption with credentials:redis://user:pass@host:port - Secrets: Never cache sensitive data (tokens, passwords, PII) without encryption
- Network: Use TLS for Redis in production (
rediss://protocol) - Eviction: Cached data persists until TTL expires or LRU evicts; plan accordingly
Report security issues via GitHub issues with [SECURITY] prefix.
BSD-3-Clause