NestJSMiddleTechnical
Как реализовать кэширование в NestJS?
NestJS предоставляет CacheModule из @nestjs/cache-manager. Подключите его глобально, используйте декоратор @CacheKey/@CacheTTL на контроллерах или вызывайте CACHE_MANAGER напрямую через inject.
Кэширование в NestJS
NestJS интегрируется с библиотекой cache-manager через пакет @nestjs/cache-manager. Поддерживаются in-memory хранилище (по умолчанию) и Redis через @keyv/redis или cache-manager-redis-store.
Установка и регистрация
// app.module.ts
import { CacheModule } from '@nestjs/cache-manager';
import { redisStore } from 'cache-manager-redis-store';
@Module({
imports: [
CacheModule.registerAsync({
isGlobal: true,
useFactory: async () => ({
store: await redisStore({
socket: { host: 'localhost', port: 6379 },
}),
ttl: 60, // секунд
}),
}),
],
})
export class AppModule {}
Авто-кэш через CacheInterceptor
Декоратор @UseInterceptors(CacheInterceptor) или глобальная регистрация автоматически кэшируют ответы GET-маршрутов.
import { CacheInterceptor, CacheKey, CacheTTL } from '@nestjs/cache-manager';
@Controller('products')
@UseInterceptors(CacheInterceptor)
export class ProductsController {
@Get()
@CacheKey('all-products')
@CacheTTL(120)
findAll() {
return this.productsService.findAll();
}
}
Ручное управление кэшем
import { Inject } from '@nestjs/common';
import { Cache, CACHE_MANAGER } from '@nestjs/cache-manager';
@Injectable()
export class ProductsService {
constructor(@Inject(CACHE_MANAGER) private cache: Cache) {}
async getProduct(id: string) {
const key = `product:${id}`;
const cached = await this.cache.get<Product>(key);
if (cached) return cached;
const product = await this.repo.findById(id);
await this.cache.set(key, product, 300);
return product;
}
async invalidate(id: string) {
await this.cache.del(`product:${id}`);
}
}
Глобальная регистрация интерсептора
// app.module.ts providers
{
provide: APP_INTERCEPTOR,
useClass: CacheInterceptor,
}
Подводные камни
- CacheInterceptor кэширует только GET-запросы; POST/PUT игнорируются — не стоит ожидать кэша для мутаций.
- Ключ по умолчанию = URL + query string; у разных пользователей с одинаковым URL кэш будет общим — добавляйте userId в ключ вручную.
isGlobal: trueважно указывать, иначе каждый модуль создаёт свой изолированный кэш-экземпляр.- При обновлении
@nestjs/cache-managerv2 токен инъекции изменился сCACHE_MANAGERиз@nestjs/commonна импорт из@nestjs/cache-manager— путаница ломает DI. - TTL задаётся в секундах в cache-manager v5, но в миллисекундах в старых версиях — всегда проверяйте документацию используемой версии.
- Redis-соединение не восстанавливается автоматически при обрыве — настройте
reconnectOnErrorи мониторинг. - Хранение объектов с методами (классов) в кэше теряет прототип после сериализации/десериализации — используйте plain objects или применяйте трансформацию при получении.
- CacheInterceptor не работает с WebSocket и gRPC транспортами — только HTTP.
Common mistakes
- Дает общий ответ про Node.js и не называет конкретные API NestJS.
- Не объясняет, где в lifecycle находится кэширование в NestJS.
- Не разделяет validation, authorization, business logic и persistence.
- Игнорирует ошибки, лимиты входных данных, observability и тестирование.
What the interviewer is testing
- Может объяснить кэширование в NestJS на примере кода.
- Называет ключевые API: CacheModule, CacheInterceptor.
- Использует точные API NestJS, а не вымышленные hooks/decorators/methods.
- Видит production-риски: безопасность, отказоустойчивость, логирование и тесты.