nest-cacheable
v1.0.0
Published
Advanced caching decorators for NestJS applications with support for TTL, conditional caching, stale-while-revalidate, and more
Maintainers
Readme
NestJS Cacheable
Advanced caching decorators for NestJS applications with support for TTL, conditional caching, stale-while-revalidate, and more.
Features
- 🚀 Simple Integration - Easy-to-use decorators for caching method results
- ⚡ Performance Optimized - Reduce database queries and API calls
- 🎯 Conditional Caching - Cache based on custom conditions
- 🔄 Stale-While-Revalidate - Serve stale content while refreshing in background
- 🗑️ Cache Eviction - Clear cache entries programmatically
- 📊 Event Callbacks - Monitor cache hits, misses, and errors
- 🔧 Customizable - Configure TTL, cache keys, and serialization
- 🌐 Multiple Stores - Support for Redis, Memory, and other cache stores
Installation
# Using pnpm (recommended)
pnpm add nest-cacheable
# Using npm
npm install nest-cacheable
# Using yarn
yarn add nest-cacheableQuick Start
1. Import CacheModule
import { Module } from '@nestjs/common';
import { CacheModule } from '@nestjs/cache-manager';
@Module({
imports: [
CacheModule.register({
ttl: 300, // seconds
max: 100, // maximum number of items in cache
}),
],
})
export class AppModule {}2. Use Cacheable Decorator
import { Injectable } from '@nestjs/common';
import { Cacheable, Time } from 'nest-cacheable';
@Injectable()
export class UserService {
@Cacheable({
ttl: 5 * Time.MINUTE,
cacheKey: (userId) => `user:${userId}`,
})
async getUser(userId: string) {
// This expensive operation will be cached
return await this.database.findUser(userId);
}
}Decorators
@Cacheable
Cache method results with advanced options:
@Cacheable({
// Cache expiration time in seconds
ttl: 60,
// Custom cache key
cacheKey: (id) => `product:${id}`,
// Conditional caching
cacheIf: (id) => id !== 'admin',
// Event callbacks
onHit: (key) => console.log(`Cache hit: ${key}`),
onMiss: (key) => console.log(`Cache miss: ${key}`),
onError: (error) => console.error(`Cache error: ${error}`),
// Stale-while-revalidate
staleWhileRevalidate: 30,
backgroundRefetch: true,
// Background refresh interval
refetchInterval: 60,
// Custom serialization
serialize: (data) => JSON.stringify(data),
deserialize: (cached) => JSON.parse(cached),
})
async getProduct(id: string) {
return await this.productRepository.findOne(id);
}@CacheEvict
Clear cache entries:
@CacheEvict({
// Cache key to evict
cacheKey: (id) => `product:${id}`,
// Clear before method execution
beforeInvocation: false,
// Clear all cache entries
all: false,
// Exact key match or pattern
exact: true,
})
async updateProduct(id: string, data: UpdateProductDto) {
return await this.productRepository.update(id, data);
}Advanced Usage
Time Utilities
import { Time } from 'nest-cacheable';
@Cacheable({
ttl: 2 * Time.HOUR, // 2 hours
// or
ttl: 30 * Time.MINUTE, // 30 minutes
// or
ttl: 7 * Time.DAY, // 7 days
})Multiple Cache Keys
@Cacheable({
cacheKey: (userId, filters) => [
`user:${userId}`,
`filters:${JSON.stringify(filters)}`,
],
})
async getUserData(userId: string, filters: any) {
// Method implementation
}Conditional Caching
@Cacheable({
cacheIf: async (userId) => {
// Only cache for non-admin users
const user = await this.getUser(userId);
return user.role !== 'admin';
},
})
async getSensitiveData(userId: string) {
// Method implementation
}Stale-While-Revalidate Pattern
@Cacheable({
ttl: 60, // Cache for 60 seconds
staleWhileRevalidate: 30, // Serve stale for 30 more seconds
backgroundRefetch: true, // Refresh in background
})
async getFrequentlyAccessedData() {
// Method implementation
}Cache Eviction Patterns
// Clear specific cache entry
@CacheEvict({
cacheKey: (id) => `item:${id}`,
})
async deleteItem(id: string) {
// Method implementation
}
// Clear all cache entries
@CacheEvict({
all: true,
})
async clearAllCache() {
// Method implementation
}
// Clear before method execution
@CacheEvict({
cacheKey: (id) => `item:${id}`,
beforeInvocation: true,
})
async updateItem(id: string, data: any) {
// Method implementation
}Redis Configuration
For production use, Redis is recommended:
import { Module } from '@nestjs/common';
import { CacheModule } from '@nestjs/cache-manager';
import { redisStore } from 'cache-manager-redis-store';
@Module({
imports: [
CacheModule.register({
store: redisStore,
host: 'localhost',
port: 6379,
ttl: 600,
}),
],
})
export class AppModule {}Best Practices
- Choose appropriate TTL values - Consider data freshness requirements
- Use meaningful cache keys - Include all parameters that affect the result
- Monitor cache performance - Use event callbacks to track hit rates
- Handle errors gracefully - Implement
onErrorcallbacks - Clear cache strategically - Use
@CacheEvictafter data modifications
API Reference
CacheableOptions
| Option | Type | Description |
| ---------------------- | -------------------------------- | --------------------------------------------------- |
| ttl | number | Cache expiration time in seconds |
| cacheKey | string \| string[] \| Function | Custom cache key definition |
| cacheIf | Function | Condition to determine if caching should be applied |
| serialize | Function | Custom serialization function |
| deserialize | Function | Custom deserialization function |
| staleWhileRevalidate | number | Time to serve stale content while refreshing |
| backgroundRefetch | boolean | Enable background refresh |
| refetchInterval | number | Background refresh interval in seconds |
| onError | Function | Error callback |
| onSuccess | Function | Success callback |
| onHit | Function | Cache hit callback |
| onMiss | Function | Cache miss callback |
CacheEvictOptions
| Option | Type | Description |
| ------------------ | -------------------------------- | ----------------------------------- |
| cacheKey | string \| string[] \| Function | Cache key(s) to evict |
| exact | boolean | Use exact key match or pattern |
| beforeInvocation | boolean | Clear cache before method execution |
| all | boolean | Clear all cache entries |
Examples
Check the examples/ directory for complete working examples:
- Basic caching
- Redis integration
- Conditional caching
- Cache eviction patterns
- Stale-while-revalidate
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
MIT License - see the LICENSE file for details.
Support
For issues and feature requests, please use the GitHub issue tracker.
