Installing Dependencies
First, install the @nestjs/cache-manager package and the appropriate cache store, such as cache-manager and cache-manager-redis-store:
npm install @nestjs/cache-manager cache-manager cache-manager-redis-storeConfiguring Cache Module
Configure the cache module in app.module.ts:
// app.module.ts
import { Module } from '@nestjs/common';
import { CacheModule, CacheInterceptor } from '@nestjs/cache-manager';
import { APP_INTERCEPTOR } from '@nestjs/core';
import { UsersModule } from './users/users.module';
@Module({
imports: [
CacheModule.register({
store: 'memory',
ttl: 60, // Cache expiration time (seconds)
}),
UsersModule,
],
providers: [
{
provide: APP_INTERCEPTOR,
useClass: CacheInterceptor,
},
],
})
export class AppModule {}In-Memory Cache
The example above demonstrates how to use in-memory caching. You can choose other cache stores, such as Redis, as needed.
Interacting with Cache Store
You can interact directly with the cache store, for example:
// src/users/users.service.ts
import { Injectable, Inject } from '@nestjs/common';
import { CACHE_MANAGER } from '@nestjs/common';
import { Cache } from 'cache-manager';
@Injectable()
export class UsersService {
constructor(@Inject(CACHE_MANAGER) private cacheManager: Cache) {}
async findUserById(id: number) {
let user = await this.cacheManager.get(`user-${id}`);
if (!user) {
// Fetch user from database
user = await this.getUserFromDatabase(id);
await this.cacheManager.set(`user-${id}`, user, { ttl: 60 });
}
return user;
}
private async getUserFromDatabase(id: number) {
// Implement logic to fetch user from database
}
}Automatic Response Caching
By globally configuring CacheInterceptor, you can automatically cache controller responses:
// app.module.ts
import { Module } from '@nestjs/common';
import { CacheModule, CacheInterceptor } from '@nestjs/cache-manager';
import { APP_INTERCEPTOR } from '@nestjs/core';
import { UsersModule } from './users/users.module';
@Module({
imports: [
CacheModule.register({
store: 'memory',
ttl: 60, // Cache expiration time (seconds)
}),
UsersModule,
],
providers: [
{
provide: APP_INTERCEPTOR,
useClass: CacheInterceptor,
},
],
})
export class AppModule {}Custom Caching
You can customize cache keys and expiration times:
// src/users/users.controller.ts
import { Controller, Get, CacheKey, CacheTTL } from '@nestjs/common';
import { UsersService } from './users.service';
@Controller('users')
export class UsersController {
constructor(private usersService: UsersService) {}
@Get(':id')
@CacheKey('user-id-:id')
@CacheTTL(120)
async getUserById(@Param('id') id: string) {
return this.usersService.findUserById(+id);
}
}Using Module Globally
Register the cache module globally in app.module.ts:
// app.module.ts
import { Module } from '@nestjs/common';
import { CacheModule } from '@nestjs/cache-manager';
import { UsersModule } from './users/users.module';
@Module({
imports: [
CacheModule.register({
store: 'memory',
ttl: 60, // Cache expiration time (seconds)
}),
UsersModule,
],
})
export class AppModule {}Global Cache Override
To disable global caching for a specific controller or method, use the @CacheClear or @CacheSkip decorators:
// src/users/users.controller.ts
import { Controller, Get, CacheClear, CacheSkip } from '@nestjs/common';
import { UsersService } from './users.service';
@Controller('users')
export class UsersController {
constructor(private usersService: UsersService) {}
@Get(':id')
@CacheSkip()
async getUserById(@Param('id') id: string) {
return this.usersService.findUserById(+id);
}
}WebSocket and Microservices
When using caching with WebSocket and microservices, ensure cache consistency. For WebSocket, consider using Redis Pub/Sub to synchronize cache updates. For microservices, use a shared cache store like a Redis cluster.
Cache Tracking
You can control cache behavior by adjusting the expiration time (ttl) or using more granular cache keys.
Different Stores
You can choose different cache stores, such as Redis or Memcached, by changing the store parameter in the register method.
Asynchronous Configuration
You can use asynchronous configuration to dynamically load cache settings:
// app.module.ts
import { Module } from '@nestjs/common';
import { CacheModule, CacheInterceptor } from '@nestjs/cache-manager';
import { APP_INTERCEPTOR } from '@nestjs/core';
import { UsersModule } from './users/users.module';
@Module({
imports: [
CacheModule.registerAsync({
useFactory: () => ({
store: 'memory',
ttl: 60, // Cache expiration time (seconds)
}),
}),
UsersModule,
],
providers: [
{
provide: APP_INTERCEPTOR,
useClass: CacheInterceptor,
},
],
})
export class AppModule {}Complete Example
Here is a complete example demonstrating how to use caching in NestJS:
// app.module.ts
import { Module } from '@nestjs/common';
import { CacheModule, CacheInterceptor } from '@nestjs/cache-manager';
import { APP_INTERCEPTOR } from '@nestjs/core';
import { UsersModule } from './users/users.module';
@Module({
imports: [
CacheModule.register({
store: 'memory',
ttl: 60, // Cache expiration time (seconds)
}),
UsersModule,
],
providers: [
{
provide: APP_INTERCEPTOR,
useClass: CacheInterceptor,
},
],
})
export class AppModule {}// src/users/users.service.ts
import { Injectable, Inject } from '@nestjs/common';
import { CACHE_MANAGER } from '@nestjs/common';
import { Cache } from 'cache-manager';
@Injectable()
export class UsersService {
constructor(@Inject(CACHE_MANAGER) private cacheManager: Cache) {}
async findUserById(id: number) {
let user = await this.cacheManager.get(`user-${id}`);
if (!user) {
// Fetch user from database
user = await this.getUserFromDatabase(id);
await this.cacheManager.set(`user-${id}`, user, { ttl: 60 });
}
return user;
}
private async getUserFromDatabase(id: number) {
// Implement logic to fetch user from database
}
}// src/users/users.controller.ts
import { Controller, Get, CacheKey, CacheTTL } from '@nestjs/common';
import { UsersService } from './users.service';
@Controller('users')
export class UsersController {
constructor(private usersService: UsersService) {}
@Get(':id')
@CacheKey('user-id-:id')
@CacheTTL(120)
async getUserById(@Param('id') id: string) {
return this.usersService.findUserById(+id);
}
}



