Skip to main content
Version: Next

Caching in CommandKit

CommandKit provides a powerful caching system that helps you optimize your bot's performance by storing frequently accessed data in memory. This guide will show you how to use caching effectively in your bot.

Installation

First, install the cache package:

npm install @commandkit/cache

Setup

Add the cache plugin to your CommandKit configuration:

import { cache } from '@commandkit/cache';

export default defineConfig({
plugins: [cache()],
});

Optional: Custom Cache Provider

You can set up a custom cache provider (like Redis) for distributed caching:

import { setCacheProvider } from '@commandkit/cache';
import { RedisCache } from '@commandkit/redis';

setCacheProvider(
new RedisCache({
// Redis configuration options
}),
);

Why Use Caching?

Caching is useful when you want to:

  • Reduce API calls to external services
  • Speed up frequently accessed data
  • Minimize database queries
  • Store computed results for reuse

Basic Usage

The simplest way to use caching is with the "use cache" directive:

async function fetchUserData(userId: string) {
'use cache';

// This expensive operation will only run once for each unique userId
const userData = await db.users.findOne(userId);
return userData;
}

When you call this function multiple times with the same userId, it will only perform the database query once and return the cached result for subsequent calls.

How Caching Works

CommandKit's caching system works by:

  1. Generating a Cache Key: Each cached function call generates a unique key based on:

    • The function's identity
    • The arguments passed to the function
    • A build ID for stability
  2. Storing Results: When a function is called:

    • If the result isn't cached, the function executes and stores its result
    • If the result is cached, it's returned immediately without executing the function
  3. Automatic Cleanup: The cache system automatically:

    • Removes stale entries
    • Manages memory usage
    • Handles cache invalidation

Cache Configuration

You can configure caching behavior using the cacheTag and cacheLife functions:

async function fetchUserData(userId: string) {
'use cache';

// Configure cache behavior
cacheTag(`user:${userId}`);
cacheLife('1h');

const userData = await db.users.findOne(userId);
return userData;
}

Best Practices

  1. Choose What to Cache:

    • Cache expensive operations (API calls, database queries)
    • Cache data that doesn't change frequently
    • Don't cache sensitive or frequently changing data
  2. Set Appropriate TTL:

    • Use shorter TTL for frequently changing data
    • Use longer TTL for static data
    • Consider your data's update frequency
  3. Use Tags for Revalidation:

    • Add meaningful tags to your cache entries
    • Group related cache entries with the same tag
    • Use tags for targeted cache invalidation
  4. Monitor Cache Usage:

    • Watch memory usage
    • Adjust TTL based on usage patterns
    • Clean up stale entries when needed

Example Use Cases

Caching API Responses

async function fetchWeather(city: string) {
'use cache';

cacheTag('weather');
cacheLife('30m');

const response = await fetch(`https://api.weather.com/${city}`);
return response.json();
}

Caching Database Queries

async function getGuildSettings(guildId: string) {
'use cache';

cacheTag(`guild:${guildId}`);
cacheLife('1h');

return await db.guilds.findOne(guildId);
}

Caching Computed Results

async function calculateUserStats(userId: string) {
'use cache';

cacheTag(`user:${userId}`);
cacheTag('stats');
cacheLife('5m');

const user = await db.users.findOne(userId);
return {
level: calculateLevel(user.xp),
rank: await calculateRank(userId),
achievements: await getAchievements(userId),
};
}

Advanced Usage

Custom Cache Provider

You can create a custom cache provider by extending the CacheProvider class:

import { CacheProvider } from '@commandkit/cache';

class RedisCache extends CacheProvider {
async get<T>(key: string) {
// Implement Redis get
}

async set<T>(key: string, value: T, ttl?: number) {
// Implement Redis set
}

async delete(key: string) {
// Implement Redis delete
}
}

// Use your custom provider
setCacheProvider(new RedisCache());

Cache Cleanup

You can manually clean up stale cache entries:

import { cleanup } from '@commandkit/cache';

// Clean up entries older than 24 hours
await cleanup(24 * 60 * 60 * 1000);

Next Steps