NestJS dan Redis di Tahun 2026: Caching, Sessions, dan Pertanyaan Interview
Panduan lengkap integrasi NestJS dengan Redis untuk caching dan session management, dilengkapi pertanyaan interview untuk persiapan wawancara kerja Node.js.

Integrasi NestJS dengan Redis mengubah performa aplikasi secara signifikan dengan menggantikan query database dengan pencarian di memori. Kombinasi @nestjs/cache-manager untuk caching dan express-session dengan connect-redis untuk persistensi session mencakup dua kasus penggunaan Redis yang paling umum dalam aplikasi backend.
Caching Redis di NestJS mengurangi beban database dengan menyimpan data yang sering diakses di memori. Session management dengan Redis memungkinkan horizontal scaling dengan berbagi state session antar instance.
Mengatur @nestjs/cache-manager dengan Redis
Modul cache-manager dipindahkan ke package terpisah sejak NestJS 10. Instalasi memerlukan wrapper NestJS dan cache store yang mendasarinya. Adapter @keyv/redis adalah pendekatan yang direkomendasikan untuk integrasi Redis dengan cache-manager v5.
# Install package yang diperlukan
npm install @nestjs/cache-manager cache-manager @keyv/redisRegistrasi modul mengkonfigurasi koneksi Redis dan TTL default. Opsi isGlobal membuat cache tersedia di semua modul tanpa perlu import ulang.
import { Module } from '@nestjs/common';
import { CacheModule } from '@nestjs/cache-manager';
import KeyvRedis from '@keyv/redis';
@Module({
imports: [
CacheModule.registerAsync({
isGlobal: true,
useFactory: () => ({
stores: [
new KeyvRedis(process.env.REDIS_URL || 'redis://localhost:6379'),
],
ttl: 60000, // Default TTL dalam milidetik
}),
}),
],
})
export class AppModule {}Array stores menerima beberapa cache store untuk multi-tier caching. Environment produksi biasanya menggunakan Redis sebagai store utama, dengan fallback in-memory opsional untuk development.
Cache Injection dan Service-Level Caching
Token CACHE_MANAGER memberikan akses langsung ke cache untuk operasi level service. Pendekatan ini menawarkan kontrol lebih dibanding HTTP caching otomatis ketika business logic menentukan kapan cache harus di-invalidasi.
import { Injectable, Inject } from '@nestjs/common';
import { CACHE_MANAGER, Cache } from '@nestjs/cache-manager';
import { UsersRepository } from './users.repository';
import { User } from './user.entity';
@Injectable()
export class UsersService {
constructor(
@Inject(CACHE_MANAGER) private cache: Cache,
private usersRepository: UsersRepository,
) {}
async findById(id: string): Promise<User | null> {
// Cek cache terlebih dahulu
const cacheKey = `user:${id}`;
const cached = await this.cache.get<User>(cacheKey);
if (cached) {
return cached;
}
// Cache miss: ambil dari database
const user = await this.usersRepository.findById(id);
if (user) {
await this.cache.set(cacheKey, user, 300000); // TTL 5 menit
}
return user;
}
async update(id: string, data: Partial<User>): Promise<User> {
const user = await this.usersRepository.update(id, data);
// Invalidate cache setelah update
await this.cache.del(`user:${id}`);
return user;
}
async delete(id: string): Promise<void> {
await this.usersRepository.delete(id);
await this.cache.del(`user:${id}`);
}
}Pola cache-aside yang diimplementasikan di atas memeriksa cache sebelum query database. Invalidasi terjadi saat operasi write untuk menjaga konsistensi data antara cache dan sumber kebenaran.
HTTP Response Caching dengan Interceptor
NestJS menyediakan CacheInterceptor untuk caching respons HTTP secara otomatis. Decorator @CacheTTL() dan @CacheKey() mengkustomisasi perilaku per endpoint.
import { Controller, Get, Param, UseInterceptors } from '@nestjs/common';
import { CacheInterceptor, CacheTTL, CacheKey } from '@nestjs/cache-manager';
import { ProductsService } from './products.service';
@Controller('products')
@UseInterceptors(CacheInterceptor)
export class ProductsController {
constructor(private productsService: ProductsService) {}
@Get()
@CacheTTL(120000) // 2 menit untuk daftar produk
async findAll() {
return this.productsService.findAll();
}
@Get(':id')
@CacheTTL(300000) // 5 menit untuk produk individual
async findOne(@Param('id') id: string) {
return this.productsService.findById(id);
}
@Get('category/:category')
@CacheKey('products-by-category')
@CacheTTL(180000)
async findByCategory(@Param('category') category: string) {
return this.productsService.findByCategory(category);
}
}Interceptor secara otomatis meng-cache respons GET menggunakan URL request sebagai key default. Custom cache key berguna ketika beberapa route harus berbagi atau memiliki entri cache yang berbeda.
Session Management dengan Redis Store
Sesi HTTP yang didukung Redis memungkinkan data sesi bertahan di seluruh server restart dan scaling horizontal. Package express-session terintegrasi dengan NestJS melalui middleware.
npm install express-session connect-redis ioredis
npm install -D @types/express-sessionKonfigurasi session store memerlukan instance Redis client. Package ioredis menyediakan dukungan Redis yang lebih baik dengan clustering dan sentinel.
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import * as session from 'express-session';
import RedisStore from 'connect-redis';
import { Redis } from 'ioredis';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
const redisClient = new Redis(
process.env.REDIS_URL || 'redis://localhost:6379'
);
app.use(
session({
store: new RedisStore({ client: redisClient }),
secret: process.env.SESSION_SECRET || 'your-secret-key',
resave: false,
saveUninitialized: false,
cookie: {
secure: process.env.NODE_ENV === 'production',
httpOnly: true,
maxAge: 24 * 60 * 60 * 1000, // 24 jam
sameSite: 'lax',
},
}),
);
await app.listen(3000);
}
bootstrap();Opsi resave: false mencegah session disimpan kembali jika tidak dimodifikasi. Pengaturan saveUninitialized: false memastikan session kosong tidak memenuhi penyimpanan Redis.
Mengakses Session Data di Controller
Data session tersedia melalui objek request. Custom decorator menyederhanakan akses session di seluruh handler.
import { createParamDecorator, ExecutionContext } from '@nestjs/common';
export const GetSession = createParamDecorator(
(data: string, ctx: ExecutionContext) => {
const request = ctx.switchToHttp().getRequest();
return data ? request.session?.[data] : request.session;
},
);
// auth.controller.ts
import { Controller, Post, Body, Get } from '@nestjs/common';
import { GetSession } from './session.decorator';
import { Session } from 'express-session';
interface UserSession extends Session {
userId?: string;
role?: string;
loginAt?: Date;
}
@Controller('auth')
export class AuthController {
@Post('login')
async login(
@Body() credentials: LoginDto,
@GetSession() session: UserSession,
) {
// Validasi credentials
const user = await this.authService.validate(credentials);
// Simpan data user di session
session.userId = user.id;
session.role = user.role;
session.loginAt = new Date();
return { message: 'Login berhasil' };
}
@Post('logout')
async logout(@GetSession() session: UserSession) {
return new Promise((resolve, reject) => {
session.destroy((err) => {
if (err) reject(err);
resolve({ message: 'Logout berhasil' });
});
});
}
@Get('profile')
async getProfile(@GetSession('userId') userId: string) {
if (!userId) {
throw new UnauthorizedException('Session tidak valid');
}
return this.usersService.findById(userId);
}
}Cache Invalidation Strategies
Strategi invalidasi cache yang tepat menjaga konsistensi data. Pola yang umum termasuk time-based expiration, event-driven invalidation, dan manual purging.
import { Injectable, Inject } from '@nestjs/common';
import { CACHE_MANAGER, Cache } from '@nestjs/cache-manager';
import { OnEvent } from '@nestjs/event-emitter';
@Injectable()
export class CacheInvalidationService {
constructor(@Inject(CACHE_MANAGER) private cache: Cache) {}
// Event-driven invalidation
@OnEvent('user.updated')
async handleUserUpdate(payload: { userId: string }) {
await this.cache.del(`user:${payload.userId}`);
await this.cache.del('users:list');
}
@OnEvent('product.created')
async handleProductCreate() {
// Invalidate semua cache produk saat produk baru dibuat
await this.invalidatePattern('products:*');
}
// Pattern-based invalidation memerlukan akses Redis langsung
async invalidatePattern(pattern: string): Promise<void> {
const store = this.cache.stores[0] as any;
const redis = store?.opts?.redis || store?.redis;
if (redis) {
const keys = await redis.keys(pattern);
if (keys.length > 0) {
await redis.del(...keys);
}
}
}
// Manual cache warming
async warmCache(): Promise<void> {
const popularProducts = await this.productsService.findPopular();
for (const product of popularProducts) {
await this.cache.set(`product:${product.id}`, product, 600000);
}
}
}Rate Limiting dengan Redis
Redis menyediakan penyimpanan terdistribusi untuk rate limit counter. Package @nestjs/throttler mendukung Redis sebagai backend penyimpanan.
npm install @nestjs/throttler @nestjs/throttler-storage-redis ioredisimport { Module } from '@nestjs/common';
import { ThrottlerModule } from '@nestjs/throttler';
import { ThrottlerStorageRedisService } from '@nestjs/throttler-storage-redis';
import { Redis } from 'ioredis';
@Module({
imports: [
ThrottlerModule.forRootAsync({
useFactory: () => ({
throttlers: [
{
name: 'short',
ttl: 1000,
limit: 3,
},
{
name: 'medium',
ttl: 10000,
limit: 20,
},
{
name: 'long',
ttl: 60000,
limit: 100,
},
],
storage: new ThrottlerStorageRedisService(
new Redis(process.env.REDIS_URL || 'redis://localhost:6379')
),
}),
}),
],
})
export class AppModule {}Siap menguasai wawancara Node.js / NestJS Anda?
Berlatih dengan simulator interaktif, flashcards, dan tes teknis kami.
Pertanyaan Interview: Caching dan Redis di NestJS
Berikut adalah pertanyaan interview umum yang menguji pemahaman tentang integrasi Redis dalam aplikasi NestJS.
Pertanyaan 1: Apa perbedaan antara cache-aside dan read-through caching?
Cache-aside mengharuskan kode aplikasi secara eksplisit memeriksa cache dan mengisinya saat cache miss. Read-through caching mendelegasikan proses ini ke cache layer itu sendiri. NestJS cache-manager menggunakan pola cache-aside di mana developer bertanggung jawab atas logika get/set.
Pertanyaan 2: Bagaimana cara menangani cache stampede?
Cache stampede terjadi ketika banyak request secara bersamaan menemukan cache miss dan semuanya query database. Solusinya termasuk request coalescing (mengantri request duplikat), probabilistic early expiration, atau lock-based population di mana hanya satu request yang mengisi cache sementara yang lain menunggu.
Pertanyaan 3: Mengapa menggunakan Redis untuk session daripada session berbasis memori?
Session berbasis memori tidak bertahan saat server restart dan tidak dapat dibagikan antar beberapa instance. Redis memberikan persistensi, horizontal scaling, dan fitur expiration bawaan untuk manajemen session.
Pertanyaan 4: Jelaskan perbedaan antara cache TTL dan sliding expiration?
TTL tetap meng-expire entri pada interval yang ditetapkan sejak pembuatan. Sliding expiration mereset timer setiap kali data diakses. Redis native hanya mendukung TTL tetap; sliding expiration memerlukan logika aplikasi untuk memperbarui waktu expiration saat read.
Pertanyaan 5: Bagaimana cara meng-cache data yang berbeda per user?
Gunakan cache key yang menyertakan user identifier: user:${userId}:preferences. Ini memastikan isolasi antara data user yang berbeda sambil tetap mendapatkan manfaat dari caching.
Pertanyaan 6: Apa trade-off antara cache hit rate dan memory usage?
TTL yang lebih tinggi meningkatkan hit rate tetapi mengkonsumsi lebih banyak memori dan berisiko data menjadi stale. TTL yang lebih pendek menjaga data tetap fresh tetapi meningkatkan load database. Solusi optimal menyeimbangkan kedua faktor berdasarkan pola akses dan sensitivitas data.
Kesimpulan
Integrasi Redis dengan NestJS memerlukan pemahaman tentang pola caching, strategi session management, dan pertimbangan konfigurasi. Module @nestjs/cache-manager menyediakan abstraksi yang bersih untuk operasi caching, sementara express-session dengan connect-redis menangani persistensi session. Kombinasi keduanya memungkinkan aplikasi NestJS untuk scaling secara horizontal sambil mempertahankan performa dan state management yang konsisten.
Bisakah kamu menemukan bug di Node.js / NestJS?
Satu potongan kode nyata, satu bug tersembunyi, satu percobaan per hari. Tanpa akun untuk mencoba.

Ditulis oleh
Anthony Fillion-MailletPendiri SharpSkill
Developer fullstack selama lebih dari 10 tahun. Ia menjalankan SharpSkill dan bertanggung jawab atas semua yang diterbitkan di sini.
Diperbarui 10 September 2026
Tag
Bagikan
Artikel terkait

NestJS dan MongoDB di 2026: Mongoose, Agregasi, dan Pertanyaan Interview
Kuasai NestJS dengan MongoDB dan Mongoose 9. Pelajari desain schema, pipeline agregasi, dan persiapan interview teknis dengan contoh praktis.

NestJS dan WebSockets di 2026: Real-Time, Gateway, dan Pertanyaan Wawancara
Panduan lengkap untuk membangun aplikasi real-time dengan NestJS dan WebSockets, termasuk implementasi gateway, best practices, dan persiapan wawancara teknis.

Microservices dengan NestJS di 2026: Arsitektur, gRPC, dan Pertanyaan Wawancara
Panduan lengkap arsitektur microservices NestJS dengan gRPC: transport layer, Protocol Buffers, streaming patterns, dan pertanyaan wawancara untuk backend engineer di 2026.