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+
constobcache=require('obcachejs');constcache=newobcache.Create({max: 1000,maxAge: 60000});constgetUser=cache.wrap(function(id,callback){// Simulate async database lookupsetTimeout(()=>callback(null,{ id,name: 'User '+id}),10);});// Promise styleconstuser=awaitgetUser(123);console.log(user);// { id: 123, name: 'User 123' }// Callback stylegetUser(456,(err,user)=>console.log(user));Creates a cache instance.
constcache=newobcache.Create({max: 1000,// max keys (default: 1000)maxAge: 60000,// TTL in msqueueEnabled: 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
constcached=cache.wrap(myAsyncFn);// Exclude arguments from key generationconstcached=cache.wrap(function(id,timestamp,cb){// timestamp won't affect cache keycb(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 hitsmiss: 0,// cache missesreset: 0,// number of resetspending: 0// queued requests}constcache=newobcache.Create({max: 10000,maxAge: 300000,id: 1,// required for Redisredis: {host: 'localhost',port: 6379,connectTimeout: 5000}});// Wait for connectionif(!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 middlewareapp.get('/debug/cache',obcache.debug.view);// Console outputobcache.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.
constobcache=require('obcachejs');// or with ES modules: import obcache from 'obcachejs';constcache=newobcache.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.
MIT