2026'da NestJS ve Redis: Önbellekleme, Oturumlar ve Mülakat Soruları
NestJS'te Redis entegrasyonu için kapsamlı rehber. Cache-manager, oturum yönetimi ve invalidasyon stratejileri.

NestJS'e Redis entegrasyonu, veritabanı sorgularını bellek içi aramalarla değiştirerek uygulama performansını dönüştürür. Önbellekleme için @nestjs/cache-manager ve oturum kalıcılığı için connect-redis ile express-session kombinasyonu, backend uygulamalarındaki en yaygın iki Redis kullanım senaryosunu kapsar.
NestJS'te Redis önbellekleme, sık erişilen verileri bellekte saklayarak veritabanı yükünü azaltır. Redis ile oturum yönetimi, oturum durumunu birden fazla örnek arasında paylaşarak yatay ölçeklendirmeyi mümkün kılar.
@nestjs/cache-manager'ı Redis ile Yapılandırma
Cache-manager modülü NestJS 10'da ayrı bir pakete taşındı. Kurulum hem NestJS wrapper'ını hem de temel cache store'u gerektirir. @keyv/redis adaptörü, cache-manager v5 ile Redis entegrasyonu için önerilen yaklaşımdır.
# Install required packages
npm install @nestjs/cache-manager cache-manager @keyv/redisModül kaydı, Redis bağlantısını ve varsayılan TTL'i yapılandırır. isGlobal seçeneği, önbelleği yeniden içe aktarmaya gerek kalmadan tüm modüllerde kullanılabilir hale getirir.
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 in milliseconds
}),
}),
],
})
export class AppModule {}stores dizisi, çok katmanlı önbellekleme için birden fazla cache store kabul eder. Üretim ortamları genellikle Redis'i birincil store olarak kullanır ve geliştirme için isteğe bağlı bellek içi fallback sağlar.
Cache Enjeksiyonu ve Servis Düzeyinde Önbellekleme
CACHE_MANAGER tokeni, servis düzeyindeki işlemler için önbelleğe doğrudan erişim sağlar. Bu yaklaşım, iş mantığı önbellek invalidasyonunu belirlediğinde otomatik HTTP önbelleklemesinden daha fazla kontrol sunar.
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> {
// Check cache first
const cacheKey = `user:${id}`;
const cached = await this.cache.get<User>(cacheKey);
if (cached) {
return cached;
}
// Cache miss: fetch from database
const user = await this.usersRepository.findById(id);
if (user) {
await this.cache.set(cacheKey, user, 300000); // 5 minutes TTL
}
return user;
}
async update(id: string, data: Partial<User>): Promise<User> {
const user = await this.usersRepository.update(id, data);
// Invalidate cache on update
await this.cache.del(`user:${id}`);
return user;
}
}user:{id} önbellek anahtarı deseni, hedefli invalidasyonu mümkün kılar. user:* gibi daha karmaşık desenler, temel istemci aracılığıyla Redis'e özgü komutlar gerektirir.
Otomatik HTTP Yanıt Önbellekleme için CacheInterceptor
Yerleşik CacheInterceptor, HTTP GET yanıtlarını otomatik olarak önbelleğe alır. Controller düzeyinde uygulamak tüm GET endpoint'lerini önbelleğe alırken, method düzeyinde uygulama granüler kontrol sağlar.
import { Controller, Get, UseInterceptors, Param } 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) // Override default TTL: 2 minutes
async findAll() {
return this.productsService.findAll();
}
@Get(':id')
@CacheKey('product-detail') // Custom cache key prefix
async findOne(@Param('id') id: string) {
return this.productsService.findById(id);
}
}Interceptor varsayılan olarak istek URL'sinden önbellek anahtarları üretir. Özel @CacheKey() dekoratörleri, sorgu parametrelerinin önbelleklemeyi etkilememesi gereken rotalar için bu davranışı geçersiz kılar. NestJS'teki interceptor ve guard kavramları teknik mülakatlarda sıkça karşılaşılır.
Varsayılan önbellek anahtarı, sorgu parametreleri dahil tam URL'yi kullanır. /products?page=1 ve /products?page=2 için iki istek ayrı önbellek girişleri oluşturur. Sayfalama yinelenen önbellek yanıtları oluşturmaması gerektiğinde @CacheKey() ile geçersiz kılın.
Redis ve express-session ile Oturum Yönetimi
NestJS varsayılan olarak Express üzerinde çalışır, bu da express-session'ı oturum yönetimi için standart seçim yapar. connect-redis adaptörü oturum verilerini bellek yerine Redis'te depolar ve sunucu yeniden başlatmalarında oturum kalıcılığını sağlar.
# Install session packages
npm install express-session connect-redis redis
npm install -D @types/express-sessionOturum yapılandırması uygulama başlamadan önce main.ts'de gerçekleşir. Redis istemcisi cache-manager kurulumundan bağımsız olarak bağlanır.
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import * as session from 'express-session';
import { createClient } from 'redis';
import RedisStore from 'connect-redis';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
// Initialize Redis client
const redisClient = createClient({
url: process.env.REDIS_URL || 'redis://localhost:6379',
});
await redisClient.connect();
// Configure session middleware
app.use(
session({
store: new RedisStore({ client: redisClient }),
secret: process.env.SESSION_SECRET || 'change-this-in-production',
resave: false,
saveUninitialized: false,
cookie: {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
maxAge: 24 * 60 * 60 * 1000, // 24 hours
},
}),
);
await app.listen(3000);
}
bootstrap();saveUninitialized: false seçeneği boş oturumların kaydedilmesini önleyerek Redis bellek kullanımını azaltır. secure: true çerez ayarı üretimde HTTPS gerektirir.
Node.js / NestJS mülakatlarında başarılı olmaya hazır mısın?
İnteraktif simülatörler, flashcards ve teknik testlerle pratik yap.
Controller ve Guard'larda Oturumlara Erişim
Oturum verileri request nesnesi aracılığıyla erişilebilir. Tipli bir oturum arayüzü geliştirici deneyimini iyileştirir ve derleme zamanında hataları yakalar.
export interface SessionData {
userId?: string;
email?: string;
roles?: string[];
loginAt?: Date;
}
declare module 'express-session' {
interface SessionData {
userId?: string;
email?: string;
roles?: string[];
loginAt?: Date;
}
}Genişletilmiş oturum tipi, oturum özelliklerini otomatik tamamlama ile kullanılabilir hale getirir.
import { Controller, Post, Body, Req, HttpCode } from '@nestjs/common';
import { Request } from 'express';
import { AuthService } from './auth.service';
import { LoginDto } from './dto/login.dto';
@Controller('auth')
export class AuthController {
constructor(private authService: AuthService) {}
@Post('login')
@HttpCode(200)
async login(@Body() loginDto: LoginDto, @Req() req: Request) {
const user = await this.authService.validateUser(
loginDto.email,
loginDto.password,
);
// Store user data in session
req.session.userId = user.id;
req.session.email = user.email;
req.session.roles = user.roles;
req.session.loginAt = new Date();
return { message: 'Logged in successfully' };
}
@Post('logout')
@HttpCode(200)
async logout(@Req() req: Request) {
return new Promise((resolve, reject) => {
req.session.destroy((err) => {
if (err) reject(err);
resolve({ message: 'Logged out successfully' });
});
});
}
}Bir guard, oturum geçerliliğini kontrol ederek rotaları korur. Bu desen, NestJS'in yetkilendirme ve RBAC sistemiyle sorunsuz entegre olur.
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
import { Request } from 'express';
@Injectable()
export class SessionGuard implements CanActivate {
canActivate(context: ExecutionContext): boolean {
const request = context.switchToHttp().getRequest<Request>();
return !!request.session?.userId;
}
}NestJS Uygulamalarında Önbellek Invalidasyon Stratejileri
Önbellek invalidasyonu, önbelleklemedeki daha zor problemdir. Üç strateji farklı senaryolara uygulanır:
Zamana dayalı sona erme (TTL) tahmin edilebilir şekilde değişen veya hafif eskiliğin kabul edilebilir olduğu veriler için çalışır. Ürün katalogları, yapılandırma değerleri ve genel içerik bu desene uyar.
Olay tabanlı invalidasyon temel veriler değiştiğinde önbellek girişlerini temizler. Bu, güncelleme ve silme işlemlerinde açık cache.del() çağrıları gerektirir.
Desen tabanlı invalidasyon birden fazla ilişkili anahtarı kaldırır. Redis, SCAN ve DEL komutları aracılığıyla desen silmeyi destekler, ancak cache-manager bunu soyutlar.
import { Injectable, Inject } from '@nestjs/common';
import { CACHE_MANAGER, Cache } from '@nestjs/cache-manager';
@Injectable()
export class CacheInvalidationService {
constructor(@Inject(CACHE_MANAGER) private cache: Cache) {}
// Single key invalidation
async invalidateUser(userId: string): Promise<void> {
await this.cache.del(`user:${userId}`);
}
// Multiple related keys
async invalidateUserRelated(userId: string): Promise<void> {
const keys = [
`user:${userId}`,
`user:${userId}:profile`,
`user:${userId}:preferences`,
];
await Promise.all(keys.map((key) => this.cache.del(key)));
}
// Clear entire cache (use sparingly)
async clearAll(): Promise<void> {
await this.cache.reset();
}
}reset() metodu tüm önbelleğe alınmış verileri temizler, dağıtımlar veya veri geçişleri sırasında yararlıdır ancak yanlışlıkla çağrılırsa üretimde tehlikelidir.
Redis Bağlantı Havuzlama ve Küme Desteği
Üretim dağıtımları, eşzamanlı istekleri verimli bir şekilde işlemek için bağlantı havuzlaması gerektirir. ioredis kütüphanesi, küme desteği ve bağlantı havuzlamasını hazır olarak sağlar.
import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import Redis, { Cluster } from 'ioredis';
@Injectable()
export class RedisConfig {
constructor(private configService: ConfigService) {}
createClient(): Redis | Cluster {
const clusterNodes = this.configService.get<string>('REDIS_CLUSTER_NODES');
if (clusterNodes) {
// Cluster mode
const nodes = clusterNodes.split(',').map((node) => {
const [host, port] = node.split(':');
return { host, port: parseInt(port, 10) };
});
return new Redis.Cluster(nodes, {
redisOptions: {
password: this.configService.get('REDIS_PASSWORD'),
},
});
}
// Standalone mode
return new Redis({
host: this.configService.get('REDIS_HOST', 'localhost'),
port: this.configService.get('REDIS_PORT', 6379),
password: this.configService.get('REDIS_PASSWORD'),
maxRetriesPerRequest: 3,
});
}
}TypeORM veya Prisma kullanan uygulamalar için veritabanı ve önbellek bağlantıları kendi bağlantı havuzlarıyla ayrı olarak yapılandırılmalıdır.
NestJS Redis Mülakat Soruları
Node.js önbellekleme üzerine teknik mülakatlar hem kavramsal anlayışı hem de pratik uygulamayı kapsar. Bu sorular sıkça karşılaşılır:
Bellek içi önbellekleme yerine neden Redis kullanılır?
Bellek içi önbellekleme yeniden başlatmalarda kalıcı değildir ve birden fazla örnek arasında paylaşılamaz. Redis, yatay olarak ölçeklenen uygulamalar için kalıcılık, replikasyon ve paylaşılan durum sağlar. Değiş tokuş, yerel bellek erişimine kıyasla ağ gecikmesidir.
cache-manager doğrudan Redis kullanımından nasıl farklıdır?
cache-manager kütüphanesi, farklı cache store'lar arasında birleşik bir API sağlar. Bellekten Redis'e geçiş, servis kodunu değiştirmeden store yapılandırmasının değiştirilmesini gerektirir. Doğrudan Redis kullanımı, pub/sub, sorted sets ve Lua scripting gibi daha fazla Redis'e özgü özellik sunar.
Cache stampede nedir ve nasıl önlenir?
Cache stampede, popüler bir önbellek girişi sona erdiğinde ve birçok eşzamanlı istek aynı anda veritabanına gittiğinde oluşur. Önleme stratejileri şunları içerir:
- Kilitleme tabanlı yenileme: Bir istek önbelleği yenilerken diğerleri bekler
- Olasılıksal erken sona erme: TTL sona ermeden önce rastgele yenileme
- Arka plan yenileme: Ayrı bir işlem sona eren girişleri yeniler
CacheInterceptor vs. servis düzeyinde önbellekleme ne zaman kullanılmalı?
CacheInterceptor, yanıtın yalnızca URL'ye bağlı olduğu durumsuz GET endpoint'leri için uygundur. Servis düzeyinde önbellekleme, önbellek invalidasyonunun veri değişikliklerinde gerçekleşmesi gerektiği veya GET olmayan işlemlerin önbellekleme gerektirdiği senaryoları ele alır.
Redis oturumlarıyla session fixation saldırıları nasıl ele alınır?
Kimlik doğrulamadan sonra oturum kimliğini yeniden oluşturun. Kullanıcı kimlik bilgilerini saklamadan önce req.session.regenerate() çağrısı, saldırganların kimlik doğrulama öncesi oturum kimliklerini kullanmasını önler.
// Secure login with session regeneration
async login(@Body() loginDto: LoginDto, @Req() req: Request) {
const user = await this.authService.validateUser(
loginDto.email,
loginDto.password,
);
return new Promise((resolve, reject) => {
req.session.regenerate((err) => {
if (err) reject(err);
req.session.userId = user.id;
req.session.email = user.email;
resolve({ message: 'Logged in successfully' });
});
});
}Kıdemli adaylar önbellekleme stratejileri arasındaki değiş tokuşları açıklar. Bir junior "önbellekleme performansı artırır" diyebilir. Bir senior, önbelleklemenin ne zaman fayda olmadan karmaşıklık eklediğini açıklar, örneğin yüksek düzeyde kişiselleştirilmiş veya hızla değişen veriler için.
Performans İzleme ve Redis Metrikleri
Üretim uygulamaları önbellek performansına görünürlük gerektirir. Temel metrikler şunları içerir:
- Hit rate: Önbellekten sunulan isteklerin yüzdesi. %80'in altında TTL veya anahtar stratejisi sorunlarını gösterir.
- Bellek kullanımı: Redis
INFO memorykomutu mevcut ve en yüksek belleği gösterir. - Bağlantı sayısı: Çok fazla bağlantı eksik havuzlamayı gösterir.
- Tahliye sayısı: Sıfır olmayan tahliyeler önbelleğin dolu olduğu ve girişleri düşürdüğü anlamına gelir.
import { Injectable } from '@nestjs/common';
import Redis from 'ioredis';
@Injectable()
export class RedisHealthService {
constructor(private redis: Redis) {}
async getMetrics() {
const info = await this.redis.info('stats');
const memory = await this.redis.info('memory');
const stats = this.parseInfo(info);
const mem = this.parseInfo(memory);
const hits = parseInt(stats.keyspace_hits, 10);
const misses = parseInt(stats.keyspace_misses, 10);
const hitRate = hits / (hits + misses) || 0;
return {
hitRate: (hitRate * 100).toFixed(2) + '%',
usedMemory: mem.used_memory_human,
connectedClients: stats.connected_clients,
evictedKeys: stats.evicted_keys,
};
}
private parseInfo(info: string): Record<string, string> {
return info.split('\n').reduce((acc, line) => {
const [key, value] = line.split(':');
if (key && value) acc[key.trim()] = value.trim();
return acc;
}, {} as Record<string, string>);
}
}Bu metrikleri bir health check endpoint'i aracılığıyla gösterin veya üretim izleme için Prometheus ile entegre edin.
Üretim NestJS Dağıtımlarında Redis Önbellekleme ve Oturumlar
Redis ile NestJS dağıtımı birkaç operasyonel endişeye dikkat gerektirir:
- Bağlantı dizesi yönetimi: Redis URL'lerini kodda değil ortam değişkenlerinde saklayın. Parolalar için secrets management kullanın.
- Zarif kapatma: Bağlantı sızıntılarını önlemek için uygulama kapatılırken Redis bağlantılarını kapatın.
- Yeniden deneme mantığı: Redis bağlantı hataları için üstel geri çekilme yapılandırın.
- Ayrı Redis örnekleri: Önbellek ve oturumlar için ayrı Redis örnekleri düşünün. Önbellek tahliyesi oturum verilerini etkilememelidir.
import { Injectable, OnModuleDestroy } from '@nestjs/common';
import Redis from 'ioredis';
@Injectable()
export class RedisCleanup implements OnModuleDestroy {
constructor(private redis: Redis) {}
async onModuleDestroy() {
await this.redis.quit();
}
}Mikroservis mimarileri için Redis, NestJS'in yerleşik taşıma katmanı aracılığıyla mesaj aracısı olarak da hizmet eder ve önbellekleme, oturumlar ve servisler arası iletişimi birleştirir.
Pratik yapmaya başla!
Mülakat simülatörleri ve teknik testlerle bilgini test et.
Node.js / NestJS kodundaki hatayı bulabilir misin?
Gerçek bir kod parçası, gizli bir hata, günde bir deneme. Denemek için hesap gerekmez.

Yazan:
Anthony Fillion-MailletSharpSkill kurucusu
10 yılı aşkın süredir fullstack geliştirici. SharpSkill’i yönetiyor ve burada yayımlanan her şeyden sorumlu.
10 Eylül 2026 tarihinde güncellendi
Paylaş
İlgili makaleler

2026'da Hızlı JavaScript ListView: Windowing, Sanallaştırma ve Performans Optimizasyonu
JavaScript'te binlerce öğeyi render etmek için windowing ve sanallaştırma tekniklerini keşfedin. TanStack Virtual, react-virtuoso ve 2026'da verimli listeler için en iyi uygulamalar.

2026'da Yüksek Performanslı JavaScript ListView: Sanallaştırma ve Optimizasyon Teknikleri
TanStack Virtual, react-virtuoso ve react-window ile JavaScript liste sanallaştırmasında uzmanlaşın. Windowing teknikleriyle 100 binden fazla öğeyi akıcı şekilde render edin.

2026'da NestJS ve MongoDB: Mongoose, Aggregation'lar ve Mülakat Soruları
NestJS ile MongoDB ve Mongoose 9 konusunda uzmanlaşın. Şema tasarım kalıplarını, aggregation pipeline'larını öğrenin ve pratik örneklerle teknik mülakatlarına hazırlanın.