A high-performance, type-safe caching library powered by ts-cache, supporting memory and Redis drivers with advanced caching patterns.
Installation
bunadd@stacksjs/cache
Basic Usage
import{cache,createCache,createMemoryCache,createRedisCache}from'@stacksjs/cache'// Use the default memory cacheawaitcache.set('key','value',60)// 60 second TTLconstvalue=awaitcache.get('key')// Create a Redis cacheconstredisCache=createRedisCache({host:'localhost',port:6379,prefix:'myapp'})// Use factory functionconstcustomCache=createCache('memory',{maxKeys:1000})
Configuration
Memory Cache Options
import{createMemoryCache}from'@stacksjs/cache'constcache=createMemoryCache({// Default TTL in seconds (0 = no expiration)stdTTL:0,// Check period for expired keys (seconds)checkPeriod:600,// Maximum number of keys (-1 = unlimited)maxKeys:-1,// Clone values on get/set (safer but slower)useClones:true,// Key prefix for namespacingprefix:'myapp:'})
Redis Cache Options
import{createRedisCache}from'@stacksjs/cache'constcache=createRedisCache({// Redis connection URL (overrides host/port)url:'redis://localhost:6379',// Or use individual settingshost:'localhost',port:6379,username:'default',password:'secret',database:0,// Enable TLStls:true,// Default TTL in secondsstdTTL:3600,// Key prefixprefix:'myapp:'})
Core Operations
Getting and Setting
// Set a value with TTL (seconds)awaitcache.set('user:1',{name:'John'},3600)// Set forever (no expiration)awaitcache.setForever('config',{theme:'dark'})// Get a valueconstuser=awaitcache.get<User>('user:1')// Get or set (fetch if missing)constdata=awaitcache.getOrSet('expensive-data',async()=>{returnawaitcomputeExpensiveData()},600)
Checking Existence
// Check if key existsconstexists=awaitcache.has('user:1')// Check if key is missingconstmissing=awaitcache.missing('user:1')
Deleting
// Delete single keyawaitcache.del('user:1')// Or use removeawaitcache.remove('user:1')// Delete multiple keysawaitcache.del(['user:1','user:2','user:3'])awaitcache.deleteMany(['key1','key2'])// Clear all cacheawaitcache.flush()// Orawaitcache.clear()
Bulk Operations
// Get multiple keysconstvalues=awaitcache.mget<User>(['user:1','user:2','user:3'])// Returns: { 'user:1': User, 'user:2': User, ... }// Set multiple keysawaitcache.mset([{key:'user:1',value:user1,ttl:3600},{key:'user:2',value:user2,ttl:3600},{key:'user:3',value:user3}// Uses default TTL])
TTL Management
// Get TTL of a key (seconds remaining)constttl=awaitcache.getTtl('user:1')// Update TTL of existing keyawaitcache.ttl('user:1',7200)// Extend to 2 hours
Take (Get and Delete)
// Get value and remove from cache atomicallyconstuser=awaitcache.take<User>('user:1')// Value is now deleted from cache
Listing Keys
// Get all keysconstallKeys=awaitcache.keys()// Get keys matching patternconstuserKeys=awaitcache.keys('user:*')
Cache Statistics
conststats=awaitcache.getStats()console.log(stats.hits)// Number of cache hitsconsole.log(stats.misses)// Number of cache missesconsole.log(stats.keys)// Total number of keysconsole.log(stats.size)// Memory size (if available)console.log(stats.hitRate)// Hit rate percentage
import{WriteThroughPattern}from'@stacksjs/cache'constwriteThrough=newWriteThroughPattern(cache,{defaultTtl:3600,writeToStore:async(key,value)=>{// Write to databaseawaitdb.updateTable('users').set(value).where('id','=',key.split(':')[1]).execute()}})// Updates cache and databaseawaitwriteThrough.set('user:1',{name:'Jane'})
Refresh-Ahead Pattern
import{RefreshAheadPattern}from'@stacksjs/cache'constrefreshAhead=newRefreshAheadPattern(cache,{ttl:3600,refreshThreshold:300,// Refresh when TTL < 5 minutesfetcher:async(key)=>{returnawaitfetchDataForKey(key)}})// Proactively refreshes before expirationconstdata=awaitrefreshAhead.get('data:key')
Multi-Level Cache
import{MultiLevelPattern}from'@stacksjs/cache'constl1Cache=createMemoryCache({maxKeys:1000})constl2Cache=createRedisCache({host:'localhost'})constmultiLevel=newMultiLevelPattern([l1Cache,l2Cache],{defaultTtl:3600})// Checks L1 first, then L2, populates missing levelsconstvalue=awaitmultiLevel.get('key')
Utility Classes
Rate Limiter
import{RateLimiter}from'@stacksjs/cache'constlimiter=newRateLimiter(cache,{points:100,// Max requestsduration:60,// Per 60 secondskeyPrefix:'rl:'})// Check and consumeconstresult=awaitlimiter.consume('user:1')if(result.allowed){// Process requestconsole.log(`Remaining: ${result.remainingPoints}`)}else{// Rate limitedconsole.log(`Retry after: ${result.retryAfter}ms`)}
Cache Lock (Distributed Locking)
import{CacheLock}from'@stacksjs/cache'constlock=newCacheLock(cache,{lockTimeout:30000,// 30 secondsretryDelay:100})// Acquire lockconstacquired=awaitlock.acquire('resource:1')if(acquired){try{// Do exclusive workawaitprocessExclusiveTask()}finally{awaitlock.release('resource:1')}}// Or use with callbackawaitlock.withLock('resource:1',async()=>{// Automatically acquires and releasesawaitprocessExclusiveTask()})
import{CacheInvalidation}from'@stacksjs/cache'constinvalidation=newCacheInvalidation(cache)// Invalidate by patternawaitinvalidation.invalidateByPattern('user:*')// Invalidate by tagsawaitcache.set('post:1',data,3600)awaitinvalidation.tag('post:1',['posts','user:1:posts'])// Later, invalidate all tagged itemsawaitinvalidation.invalidateByTag('user:1:posts')
import{memoize}from'@stacksjs/cache'// Memoize expensive functionconstmemoizedFetch=memoize(async(userId:number)=>{returnawaitfetchUserFromDB(userId)},{cache,ttl:3600,keyGenerator:(userId)=>`user:${userId}`})// Subsequent calls use cacheconstuser1=awaitmemoizedFetch(1)constuser1Again=awaitmemoizedFetch(1)// From cache
Connection Management
// Close connection (important for Redis)awaitcache.close()// Orawaitcache.disconnect()// Access underlying cache managerconstmanager=cache.cacheManager
Edge Cases
Handling Cache Misses
// Get returns undefined on missconstvalue=awaitcache.get('non-existent')if(value===undefined){// Handle cache miss}// Or use getOrSet to always have a valueconstvalue=awaitcache.getOrSet('key',()=>'default',3600)
Handling Serialization
// Complex objects are serialized automaticallyawaitcache.set('user',{name:'John',roles:['admin','user'],metadata:{lastLogin:newDate()}})// Note: Date objects become strings after serializationconstuser=awaitcache.get('user')// user.metadata.lastLogin is a string, not Date
Handling Large Values
// Memory cache with limitsconstcache=createMemoryCache({maxKeys:10000,// Large values may be truncated or rejected})// Consider chunking large dataconstlargeData=awaitgetLargeData()constchunks=chunkData(largeData,1000)for(leti=0;i<chunks.length;i++){awaitcache.set(`data:chunk:${i}`,chunks[i])}
Redis Connection Failures
try{awaitcache.set('key','value')}catch(error){if(error.code==='ECONNREFUSED'){// Redis not available, fall back to memoryconsole.warn('Redis unavailable, using fallback')}}
API Reference
Cache Driver Methods
Method
Description
get<T>(key)
Get cached value
set<T>(key, value, ttl?)
Set cached value
mget<T>(keys)
Get multiple values
mset(entries)
Set multiple values
setForever<T>(key, value)
Set without expiration
getOrSet<T>(key, fetcher, ttl?)
Get or compute and cache
has(key)
Check if key exists
missing(key)
Check if key is missing
del(keys)
Delete key(s)
remove(key)
Alias for del
deleteMany(keys)
Delete multiple keys
clear()
Clear all cache
flush()
Alias for clear
keys(pattern?)
List keys
getTtl(key)
Get TTL remaining
ttl(key, seconds)
Update TTL
take<T>(key)
Get and delete
getStats()
Get statistics
close()
Close connection
disconnect()
Alias for close
Factory Functions
Function
Description
createCache(driver, options)
Create cache by driver type
createMemoryCache(options)
Create memory cache
createRedisCache(options)
Create Redis cache
Pattern Classes
Class
Description
CacheAsidePattern
Cache-aside implementation
WriteThroughPattern
Write-through implementation
RefreshAheadPattern
Refresh-ahead implementation
MultiLevelPattern
Multi-level cache
Utility Classes
Class
Description
RateLimiter
Rate limiting
CacheLock
Distributed locking
CircuitBreaker
Circuit breaker pattern
CacheInvalidation
Tag-based invalidation
BatchOperations
Batch cache operations
Related Resources
Underlying Libraries
The Stacks cache package is built on top of these zero-dependency libraries from the Stacks ecosystem:
ts-cache - The core caching library that powers @stacksjs/cache, including its standalone documentation.
Related Stacks Packages
Queue Package - Job queues often work alongside caching for deferred operations