The @commandkit/cache plugin adds powerful caching capabilities to your CommandKit bot. Cache expensive operations, API calls, and database queries with Redis or in-memory storage.
Installation
npm install @commandkit/cache
With Redis
For production use with Redis:
npm install @commandkit/cache ioredis
Setup
Import and add the plugin
Import the cache plugin and add it to your CommandKit instance. import { CommandKit } from 'commandkit' ;
import { cache } from '@commandkit/cache' ;
new CommandKit ({
client ,
plugins: [ cache ()],
});
Configure cache provider (optional)
By default, the plugin uses in-memory caching. For production, use Redis: import { setCacheProvider , RedisCache } from '@commandkit/cache' ;
const redisCache = new RedisCache ({
host: 'localhost' ,
port: 6379 ,
});
setCacheProvider ( redisCache );
Use caching in your code
Use the "use cache" directive to cache function results: export async function fetchExpensiveData () {
"use cache" ;
// This result will be cached
const data = await db . query ( 'SELECT * FROM users' );
return data ;
}
Cache Providers
Memory Cache (Default)
The default provider stores cache in memory. Perfect for development and simple bots.
import { cache , MemoryCache , setCacheProvider } from '@commandkit/cache' ;
const memoryCache = new MemoryCache ();
setCacheProvider ( memoryCache );
new CommandKit ({
client ,
plugins: [ cache ()],
});
Memory cache is cleared when your bot restarts. Use Redis for persistence.
Redis Cache
Use Redis for production-grade caching with persistence and distributed support.
Basic Redis Setup
Redis with Options
Custom Serialization
import { RedisCache , setCacheProvider } from '@commandkit/cache' ;
const redisCache = new RedisCache ({
host: 'localhost' ,
port: 6379 ,
});
setCacheProvider ( redisCache );
Using the “use cache” Directive
The "use cache" directive automatically caches function results:
export async function fetchUserProfile ( userId : string ) {
"use cache" ;
// Set cache lifetime
cacheLife ( '1h' );
// Tag for selective invalidation
cacheTag ( `user: ${ userId } ` );
const profile = await api . get ( `/users/ ${ userId } ` );
return profile ;
}
Cache Configuration Functions
Sets the cache TTL (time-to-live) for the current function execution. Parameters:
ttl - Duration as number (milliseconds) or string (‘1h’, ‘30m’, ‘5s’)
cacheLife ( '30m' ); // 30 minutes
cacheLife ( 1800000 ); // 30 minutes in ms
Tags the cache entry for selective invalidation. Parameters:
tag - String identifier for the cache group
cacheTag ( 'user:123' );
cacheTag ( 'guild:456' );
Invalidates all cache entries with the specified tag. Parameters: Returns: Promise<void>await revalidateTag ( 'user:123' );
Cache Management
Manual Cache Control
Access the cache provider directly for manual operations:
import { getCacheProvider } from '@commandkit/cache' ;
const cache = getCacheProvider ();
// Set a value
await cache . set ( 'key' , { data: 'value' }, 60000 ); // 60 seconds
// Get a value
const entry = await cache . get ( 'key' );
if ( entry ) {
console . log ( entry . value );
}
// Check existence
const exists = await cache . exists ( 'key' );
// Delete a key
await cache . delete ( 'key' );
// Clear all cache
await cache . clear ();
// Update expiration
await cache . expire ( 'key' , 120000 ); // 2 minutes
Cleanup Stale Entries
import { cleanup } from '@commandkit/cache' ;
// Remove entries older than 24 hours
await cleanup ( 24 * 60 * 60 * 1000 );
// Run cleanup periodically
setInterval (() => {
cleanup ();
}, 60 * 60 * 1000 ); // Every hour
Examples
Caching API Responses
import { cacheLife , cacheTag } from '@commandkit/cache' ;
export async function getWeather ( city : string ) {
"use cache" ;
cacheLife ( '15m' ); // Weather updates every 15 minutes
cacheTag ( `weather: ${ city } ` );
const response = await fetch ( `https://api.weather.com/ ${ city } ` );
return response . json ();
}
Caching Database Queries
import { cacheLife , cacheTag } from '@commandkit/cache' ;
export async function getUserStats ( userId : string ) {
"use cache" ;
cacheLife ( '5m' );
cacheTag ( `user: ${ userId } ` );
const stats = await db . query (
'SELECT * FROM user_stats WHERE user_id = ?' ,
[ userId ]
);
return stats [ 0 ];
}
Invalidating Cache on Updates
import { revalidateTag } from '@commandkit/cache' ;
export const run : CommandRunOptions = async ({ interaction }) => {
const userId = interaction . user . id ;
// Update user profile
await db . updateProfile ( userId , { bio: 'New bio' });
// Invalidate cached profile data
await revalidateTag ( `user: ${ userId } ` );
await interaction . reply ( 'Profile updated!' );
};
Caching Expensive Calculations
export async function calculateServerStats ( guildId : string ) {
"use cache" ;
cacheLife ( '1h' );
cacheTag ( `guild: ${ guildId } :stats` );
// Expensive computation
const messages = await db . query (
'SELECT COUNT(*) FROM messages WHERE guild_id = ?' ,
[ guildId ]
);
const activeUsers = await db . query (
'SELECT COUNT(DISTINCT user_id) FROM messages WHERE guild_id = ? AND created_at > NOW() - INTERVAL 7 DAY' ,
[ guildId ]
);
return {
totalMessages: messages [ 0 ]. count ,
activeUsers: activeUsers [ 0 ]. count ,
};
}
Advanced Usage
Conditional Caching
export async function fetchData ( userId : string , skipCache = false ) {
"use cache" ;
if ( ! skipCache ) {
cacheLife ( '10m' );
cacheTag ( `data: ${ userId } ` );
} else {
cacheLife ( 0 ); // Don't cache
}
return await api . fetch ( userId );
}
export async function getGuildMember ( guildId : string , userId : string ) {
"use cache" ;
cacheLife ( '30m' );
cacheTag ( `guild: ${ guildId } ` );
cacheTag ( `user: ${ userId } ` );
return await db . members . findOne ({ guildId , userId });
}
// Invalidate all guild data
await revalidateTag ( `guild: ${ guildId } ` );
// Or just one user
await revalidateTag ( `user: ${ userId } ` );
Custom Cache Provider
Implement your own cache provider:
src/utils/custom-cache.ts
import { CacheProvider , CacheEntry } from '@commandkit/cache' ;
export class CustomCache extends CacheProvider {
private store = new Map < string , CacheEntry >();
async get < T >( key : string ) : Promise < CacheEntry < T > | undefined > {
const entry = this . store . get ( key ) as CacheEntry < T >;
if ( entry && entry . ttl && Date . now () > entry . ttl ) {
this . store . delete ( key );
return undefined ;
}
return entry ;
}
async set < T >( key : string , value : T , ttl ?: number ) : Promise < void > {
this . store . set ( key , {
value ,
ttl: ttl ? Date . now () + ttl : undefined ,
});
}
async exists ( key : string ) : Promise < boolean > {
return this . store . has ( key );
}
async delete ( key : string ) : Promise < void > {
this . store . delete ( key );
}
async clear () : Promise < void > {
this . store . clear ();
}
async expire ( key : string , ttl : number ) : Promise < void > {
const entry = this . store . get ( key );
if ( entry ) {
entry . ttl = Date . now () + ttl ;
}
}
}
Best Practices
Set Appropriate TTLs Choose cache lifetimes based on data freshness requirements. Use shorter TTLs for frequently changing data.
Use Cache Tags Tag cache entries for easy invalidation when related data changes.
Use Redis in Production Memory cache is great for development, but use Redis for production deployments.
Monitor Cache Performance Track cache hits/misses using CommandKit analytics to optimize your caching strategy.
API Reference
cache(options?)
Creates the cache plugin instance.
Returns: [UseCacheDirectivePlugin, CachePlugin]
setCacheProvider(provider)
Sets the cache provider for CommandKit.
Parameters:
provider - Instance of CacheProvider
getCacheProvider()
Gets the current cache provider.
Returns: CacheProvider
Throws: Error if cache provider is not set.
cacheLife(ttl)
Sets TTL for the current cache operation. Must be called inside a cached function.
Parameters:
ttl - Number (milliseconds) or string (‘1h’, ‘30m’, ‘5s’)
cacheTag(tag)
Tags the current cache entry. Must be called inside a cached function.
Parameters:
revalidateTag(tag)
Invalidates all cache entries with the specified tag.
Parameters:
Returns: Promise<void>
cleanup(maxAge?)
Cleans up stale cache entries.
Parameters:
maxAge - Maximum age in milliseconds (default: 24 hours)
Returns: Promise<void>