NestJS en Redis in 2026: Caching, Sessies en Technische Sollicitatievragen
NestJS Redis-integratie met @nestjs/cache-manager, sessiebeheer met connect-redis en veelvoorkomende sollicitatievragen voor Node.js backend-ontwikkelaars.

De integratie van Redis in NestJS-applicaties transformeert de prestaties door database-aanroepen te vervangen door in-memory lookups. De combinatie van @nestjs/cache-manager voor caching en express-session met connect-redis voor sessiepersistentie dekt de twee meest voorkomende Redis-toepassingen in backend-applicaties.
Redis-caching in NestJS vermindert de databasebelasting door veelgebruikte gegevens in het geheugen op te slaan. Sessiebeheer met Redis maakt horizontale schaalbaarheid mogelijk door de sessiestatus te delen over meerdere instanties.
Configuratie van @nestjs/cache-manager met Redis
De cache-manager-module is verplaatst naar een apart pakket in NestJS 10. De installatie vereist zowel de NestJS-wrapper als de onderliggende cache-store. De @keyv/redis-adapter is de aanbevolen aanpak voor Redis-integratie met cache-manager v5.
# Vereiste pakketten installeren
npm install @nestjs/cache-manager cache-manager @keyv/redisDe moduleregistratie configureert de Redis-verbinding en de standaard TTL. De isGlobal-optie maakt de cache beschikbaar in alle modules zonder opnieuw te importeren.
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, // Standaard TTL in milliseconden
}),
}),
],
})
export class AppModule {}De stores-array accepteert meerdere cache-stores voor multi-tier caching. Productieomgevingen gebruiken typisch Redis als primaire store, met een optionele in-memory fallback voor ontwikkeling.
Cache-injectie en Service-Level Caching
Het CACHE_MANAGER-token biedt directe toegang tot de cache voor service-level operaties. Deze aanpak biedt meer controle dan automatische HTTP-caching wanneer de bedrijfslogica de cache-invalidatie bepaalt.
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> {
// Controleer eerst de cache
const cacheKey = `user:${id}`;
const cached = await this.cache.get<User>(cacheKey);
if (cached) {
return cached;
}
// Cache miss: ophalen uit database
const user = await this.usersRepository.findById(id);
if (user) {
await this.cache.set(cacheKey, user, 300000); // 5 minuten TTL
}
return user;
}
async update(id: string, data: Partial<User>): Promise<User> {
const user = await this.usersRepository.update(id, data);
// Cache invalideren bij update
await this.cache.del(`user:${id}`);
return user;
}
}Het cache-sleutelpatroon user:{id} maakt gerichte invalidatie mogelijk. Complexere patronen zoals user:* vereisen Redis-specifieke commando's via de onderliggende client.
CacheInterceptor voor Automatische HTTP Response Caching
De ingebouwde CacheInterceptor cached HTTP GET-responses automatisch. Toepassing op controller-niveau cached alle GET-endpoints, terwijl toepassing op methode-niveau granulaire controle biedt.
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) // Standaard TTL overschrijven: 2 minuten
async findAll() {
return this.productsService.findAll();
}
@Get(':id')
@CacheKey('product-detail') // Aangepaste cache-sleutel prefix
async findOne(@Param('id') id: string) {
return this.productsService.findById(id);
}
}De interceptor genereert standaard cache-sleutels uit de request-URL. Aangepaste @CacheKey()-decorators overschrijven dit gedrag voor routes waar query-parameters geen invloed moeten hebben op caching. NestJS-interceptors en guards zijn frequente onderwerpen in technische sollicitatiegesprekken.
De standaard cache-sleutel gebruikt de volledige URL inclusief query-parameters. Twee verzoeken naar /products?page=1 en /products?page=2 creëren afzonderlijke cache-entries. Overschrijf met @CacheKey() wanneer paginering geen dubbele gecachte responses moet creëren.
Sessiebeheer met Redis en express-session
NestJS draait standaard op Express, waardoor express-session de standaardkeuze is voor sessiebeheer. De connect-redis-adapter slaat sessiegegevens op in Redis in plaats van in het geheugen, waardoor sessiepersistentie over server-herstarts mogelijk wordt.
# Sessiepakketten installeren
npm install express-session connect-redis redis
npm install -D @types/express-sessionDe sessieconfiguratie gebeurt in main.ts voordat de applicatie start. De Redis-client verbindt onafhankelijk van de cache-manager setup.
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);
// Redis-client initialiseren
const redisClient = createClient({
url: process.env.REDIS_URL || 'redis://localhost:6379',
});
await redisClient.connect();
// Sessie-middleware configureren
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 uur
},
}),
);
await app.listen(3000);
}
bootstrap();De saveUninitialized: false-optie voorkomt het opslaan van lege sessies, waardoor Redis-geheugengebruik wordt verminderd. De secure: true-cookie-instelling vereist HTTPS in productie.
Klaar om je Node.js / NestJS gesprekken te halen?
Oefen met onze interactieve simulatoren, flashcards en technische tests.
Toegang tot Sessies in Controllers en Guards
Sessiegegevens zijn beschikbaar via het request-object. Een getypeerde sessie-interface verbetert de ontwikkelaarservaring en detecteert fouten tijdens compilatie.
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;
}
}Het uitgebreide sessietype maakt sessie-eigenschappen beschikbaar met autocompletion.
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,
);
// Gebruikersgegevens opslaan in sessie
req.session.userId = user.id;
req.session.email = user.email;
req.session.roles = user.roles;
req.session.loginAt = new Date();
return { message: 'Succesvol ingelogd' };
}
@Post('logout')
@HttpCode(200)
async logout(@Req() req: Request) {
return new Promise((resolve, reject) => {
req.session.destroy((err) => {
if (err) reject(err);
resolve({ message: 'Succesvol uitgelogd' });
});
});
}
}Een guard beschermt routes door de geldigheid van de sessie te controleren. Dit patroon integreert naadloos met het NestJS-autorisatie- en RBAC-systeem.
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;
}
}Cache-invalidatiestrategieën voor NestJS-applicaties
Cache-invalidatie is het moeilijkere probleem bij caching. Drie strategieën zijn geschikt voor verschillende scenario's:
Tijdgebaseerde vervaldatum (TTL) werkt voor gegevens die voorspelbaar veranderen of waar lichte veroudering acceptabel is. Productcatalogi, configuratiewaarden en openbare content passen in dit patroon.
Gebeurtenisgebaseerde invalidatie wist cache-entries wanneer de onderliggende gegevens veranderen. Dit vereist expliciete cache.del()-aanroepen in update- en delete-operaties.
Patroongebaseerde invalidatie verwijdert meerdere gerelateerde sleutels. Redis ondersteunt patroonverwijdering via SCAN- en DEL-commando's, maar cache-manager abstraheert dit.
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) {}
// Enkele sleutel-invalidatie
async invalidateUser(userId: string): Promise<void> {
await this.cache.del(`user:${userId}`);
}
// Meerdere gerelateerde sleutels
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)));
}
// Hele cache wissen (spaarzaam gebruiken)
async clearAll(): Promise<void> {
await this.cache.reset();
}
}De reset()-methode wist alle gecachte gegevens, nuttig tijdens deployments of datamigraties maar gevaarlijk in productie als deze per ongeluk wordt aangeroepen.
Redis Connection Pooling en Cluster-ondersteuning
Productie-deployments vereisen connection pooling om gelijktijdige verzoeken efficiënt af te handelen. De ioredis-bibliotheek biedt standaard cluster-ondersteuning en connection pooling.
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-modus
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-modus
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,
});
}
}Voor applicaties die TypeORM of Prisma gebruiken, moeten database- en cache-verbindingen afzonderlijk worden geconfigureerd met hun eigen connection pools.
NestJS Redis Sollicitatievragen
Technische sollicitatiegesprekken over Node.js-caching behandelen zowel conceptueel begrip als praktische implementatie. Deze vragen komen vaak voor:
Waarom Redis gebruiken in plaats van in-memory caching?
In-memory caching persisteert niet over herstarts en kan niet worden gedeeld over meerdere instanties. Redis biedt persistentie, replicatie en gedeelde status voor horizontaal geschaalde applicaties. De afweging is netwerklatentie vergeleken met lokale geheugentoegang.
Hoe verschilt cache-manager van direct Redis-gebruik?
De cache-manager-bibliotheek biedt een uniforme API over verschillende cache-stores. Overschakelen van in-memory naar Redis vereist alleen het wijzigen van de store-configuratie zonder de servicecode aan te passen. Direct Redis-gebruik biedt meer Redis-specifieke functies zoals pub/sub, sorted sets en Lua-scripting.
Wat is cache stampede en hoe voorkom je het?
Cache stampede treedt op wanneer een populaire cache-entry verloopt en veel gelijktijdige verzoeken tegelijkertijd de database raken. Preventiestrategieën omvatten:
- Lock-gebaseerde refresh: Eén verzoek vernieuwt de cache terwijl anderen wachten
- Probabilistische vroege vervaldatum: Willekeurige verversing voor TTL-vervaldatum
- Achtergrondverversing: Een apart proces vernieuwt verlopende entries
Wanneer CacheInterceptor vs. service-level caching gebruiken?
CacheInterceptor is geschikt voor stateless GET-endpoints waar de response alleen van de URL afhangt. Service-level caching behandelt scenario's waar cache-invalidatie moet plaatsvinden bij datawijzigingen of waar niet-GET-operaties caching nodig hebben.
Hoe voorkom je session fixation-aanvallen met Redis-sessies?
Regenereer de sessie-ID na authenticatie. Roep req.session.regenerate() aan voordat gebruikersreferenties worden opgeslagen om te voorkomen dat aanvallers pre-authenticatie sessie-ID's gebruiken.
// Veilige login met sessie-regeneratie
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: 'Succesvol ingelogd' });
});
});
}Senior kandidaten leggen de afwegingen tussen cachingstrategieën uit. Een junior zou kunnen zeggen "caching verbetert de prestaties." Een senior legt uit wanneer caching complexiteit toevoegt zonder voordeel, zoals bij sterk gepersonaliseerde of snel veranderende gegevens.
Prestatiemonitoring en Redis-metrics
Productieapplicaties hebben inzicht nodig in cacheprestaties. Belangrijke metrics omvatten:
- Hit rate: Percentage verzoeken dat uit de cache wordt bediend. Onder 80% suggereert TTL- of sleutelstrategieproblemen.
- Geheugengebruik: Het Redis
INFO memory-commando toont huidig en piekgeheugen. - Verbindingsaantal: Te veel verbindingen duiden op ontbrekende pooling.
- Eviction-aantal: Niet-nul evictions betekenen dat de cache vol is en entries verwijdert.
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>);
}
}Exposeer deze metrics via een health check-endpoint of integreer met Prometheus voor productiemonitoring.
Redis Caching en Sessies in Productie NestJS-deployments
Het deployen van NestJS met Redis vereist aandacht voor verschillende operationele aspecten:
- Connection string-beheer: Sla Redis-URL's op in omgevingsvariabelen, niet in code. Gebruik secrets-management voor wachtwoorden.
- Graceful shutdown: Sluit Redis-verbindingen tijdens applicatie-shutdown om connection leaks te voorkomen.
- Retry-logica: Configureer exponentiële backoff voor Redis-verbindingsfouten.
- Afzonderlijke Redis-instanties: Overweeg afzonderlijke Redis-instanties voor cache en sessies. Cache-eviction mag sessiegegevens niet beïnvloeden.
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();
}
}Voor microservices-architecturen dient Redis ook als message broker via de ingebouwde transportlaag van NestJS, waardoor caching, sessies en inter-service communicatie worden verenigd.
Begin met oefenen!
Test je kennis met onze gespreksimulatoren en technische tests.
Zie jij de bug in Node.js / NestJS?
Een echt codefragment, een verborgen bug, één poging per dag. Zonder account uit te proberen.

Geschreven door
Anthony Fillion-MailletOprichter van SharpSkill
Al meer dan 10 jaar fullstack-ontwikkelaar. Hij leidt SharpSkill en staat in voor alles wat hier verschijnt.
Bijgewerkt op 10 september 2026
Delen
Gerelateerde artikelen

Snelle JavaScript ListView in 2026: Windowing, Virtualisatie en Performance-optimalisatie
Leer hoe je met windowing en virtualisatie performante JavaScript ListViews bouwt. TanStack Virtual, React Virtualized en geavanceerde technieken voor 2026.

High Performance JavaScript ListView in 2026: Virtualisatie en Optimalisatietechnieken
Ontdek hoe je met JavaScript list virtualization en React Virtualized hoogperformante ListViews ontwikkelt. Deep-dive in rendering optimalisatie voor grote datasets.

NestJS en MongoDB in 2026: Mongoose, Aggregaties en Sollicitatievragen
Praktische handleiding voor NestJS 12 met MongoDB en Mongoose 9: schema-ontwerp, aggregation pipelines, transacties en technische sollicitatievragen voor backend-ontwikkelaars.