Comprehensive Guide to Caching in NestJS
Cache is a vital part of the modern web application development process as it helps applications to enhance their performance by habitual storing in memory of the frequently used data; this reduces the load on databases and different query APIs. In this tutorial, we're going to look well into how you can implement caching in a NestJS application giving light to all possible caching strategies and use cases.
Table of Contents
- Introduction to NestJS
- Understanding Caching
- Setting Up a NestJS Project
- Installing and Configuring Cache Module
- Using In-Memory Caching
- Implementing Redis Caching
- Cache Interceptors
- Cache Management
- Best Practices
- Conclusion
1. Introduction to NestJS
NestJS is a progressive Node.js framework for building efficient, reliable, and scalable server-side applications that leverage TypeScript and are based on a blend of Object-Oriented Programming and Functional Programming techniques.
2. Understanding Caching
Caching is the process of saving files or data copies in a temporary storage location to make the time to access that file or data smaller. Common cases of caching in a web application are to reduce the load on a database, to speed up the response time for data requests made frequently, and to reduce latency from APIs.
3. Setting Up a NestJS Project
Before diving into caching, let's set up a basic NestJS project.
Step 1: Install NestJS CLI
npm install -g @nestjs/cli
Step 2: Create a New Project
nest new nestjs-cache-tutorial
Step 3: Navigate to Project Directory
cd nestjs-cache-tutorial
Step 4: Start the Development Server
npm run start:dev
4. Installing and Configuring Cache Module
NestJS provides a built-in @nestjs/cache-manager
package for caching. Let's install and configure it.
Step 1: Install Cache Manager
npm install cache-manager
Step 2: Import CacheModule in AppModule
import { CacheModule, Module } from '@nestjs/common';
@Module({
imports: [
CacheModule.register({
ttl: 5, // seconds
max: 100, // maximum number of items in cache
}),
],
controllers: [],
providers: [],
})
export class AppModule {}
5. Using In-Memory Caching
Step 1: Inject CacheManager
import { Controller, Get, Inject, CACHE_MANAGER } from '@nestjs/common';
import { Cache } from 'cache-manager';
@Controller('data')
export class DataController {
constructor(@Inject(CACHE_MANAGER) private cacheManager: Cache) {}
@Get()
async getData() {
const cachedData = await this.cacheManager.get('key');
if (cachedData) {
return cachedData;
}
const data = { message: 'Hello, world!' }; // Simulate data fetching
await this.cacheManager.set('key', data, { ttl: 10 }); // Cache data for 10 seconds
return data;
}
}
6. Implementing Redis Caching
Redis is an in-memory data structure store, used as a database, cache, and message broker. Integrating Redis with NestJS enhances caching capabilities.
Step 1: Install Redis and Redis Cache Manager
npm install redis cache-manager-redis-store
Step 2: Configure Redis Cache in AppModule
import { CacheModule, Module } from '@nestjs/common';
import * as redisStore from 'cache-manager-redis-store';
@Module({
imports: [
CacheModule.register({
store: redisStore,
host: 'localhost',
port: 6379,
ttl: 600,
}),
],
controllers: [],
providers: [],
})
export class AppModule {}
Step 3: Use Redis Cache in Controller
The usage remains the same as in-memory caching. The only change is the configuration in AppModule
.
7. Cache Interceptors
NestJS provides interceptors to implement cross-cutting concerns. Cache Interceptors can automatically handle caching for controller methods.
Step 1: Create a Cache Interceptor
import {
Injectable,
CacheInterceptor,
ExecutionContext,
CallHandler,
} from '@nestjs/common';
import { Observable } from 'rxjs';
@Injectable()
export class CustomCacheInterceptor extends CacheInterceptor {
trackBy(context: ExecutionContext): string | undefined {
const request = context.switchToHttp().getRequest();
return request.method === 'GET' ? request.url : undefined;
}
}
Step 2: Apply Cache Interceptor
import { Controller, Get, UseInterceptors } from '@nestjs/common';
import { CustomCacheInterceptor } from './custom-cache.interceptor';
@Controller('data')
@UseInterceptors(CustomCacheInterceptor)
export class DataController {
@Get()
getData() {
return { message: 'Hello, world!' };
}
}
8. Cache Management
Managing cache involves setting, getting, and clearing cache data as required.
Step 1: Clear Cache Manually
@Controller('data')
export class DataController {
constructor(@Inject(CACHE_MANAGER) private cacheManager: Cache) {}
@Get('clear-cache')
async clearCache() {
await this.cacheManager.reset();
return { message: 'Cache cleared' };
}
}
9. Best Practices
- TTL Management: Set appropriate TTL values based on the nature of data.
- Cache Invalidation: Ensure cache is invalidated when underlying data changes.
- Avoid Over-Caching: Cache only frequently accessed data to avoid memory bloat.
- Monitor Cache Usage: Use monitoring tools to keep track of cache hit/miss ratios.
10. Conclusion
Implementing caching in a NestJS application can significantly boost performance and scalability. By leveraging in-memory caching and Redis, along with best practices, you can optimize your NestJS applications effectively. With the built-in caching mechanisms and flexibility of custom implementations, NestJS makes it easy to manage cache seamlessly.
Happy coding!
Sami Rahimi
Innovate relentlessly. Shape the future..
Recent Comments