NestJS

Redis Integration in NestJS: Complete Guide

Learn how to integrate Redis with NestJS for caching, session management, and real-time applications. Complete with code examples and best practices.

January 15, 2024
8 min read
By Naveed Ullah
RedisNestJSCachingPerformanceBackend
Redis Integration in NestJS: Complete Guide
Share this article:

Redis Integration in NestJS: Complete Guide

Redis is a powerful in-memory data structure store that can significantly improve your NestJS application's performance through caching, session management, and real-time features. In this comprehensive guide, we'll explore how to integrate Redis with NestJS effectively.

Why Use Redis with NestJS?

Redis offers several advantages for NestJS applications:

  • • **High Performance**: In-memory storage provides lightning-fast data access
  • • **Versatile Data Structures**: Supports strings, hashes, lists, sets, and more
  • • **Caching**: Reduce database load and improve response times
  • • **Session Management**: Store user sessions efficiently
  • • **Real-time Features**: Enable pub/sub messaging for real-time applications
  • Installation and Setup

    First, install the required packages:

    npm install redis @nestjs/redis
    

    npm install -D @types/redis

    Configuring Redis Module

    Create a Redis configuration in your NestJS application:

    // redis.module.ts
    

    import { Module } from '@nestjs/common';

    import { RedisModule as NestRedisModule } from '@nestjs/redis';

    @Module({

    imports: [

    NestRedisModule.forRoot({

    config: {

    host: process.env.REDIS_HOST || 'localhost',

    port: parseInt(process.env.REDIS_PORT) || 6379,

    password: process.env.REDIS_PASSWORD,

    db: 0,

    },

    }),

    ],

    exports: [NestRedisModule],

    })

    export class RedisModule {}

    Implementing Caching

    Basic Caching Service

    Create a caching service to handle Redis operations:

    // cache.service.ts
    

    import { Injectable } from '@nestjs/common';

    import { RedisService } from '@nestjs/redis';

    import Redis from 'redis';

    @Injectable()

    export class CacheService {

    private readonly redis: Redis;

    constructor(private readonly redisService: RedisService) {

    this.redis = this.redisService.getClient();

    }

    async get(key: string): Promise {

    return await this.redis.get(key);

    }

    async set(key: string, value: string, ttl?: number): Promise {

    if (ttl) {

    await this.redis.setex(key, ttl, value);

    } else {

    await this.redis.set(key, value);

    }

    }

    async del(key: string): Promise {

    await this.redis.del(key);

    }

    async exists(key: string): Promise {

    const result = await this.redis.exists(key);

    return result === 1;

    }

    }

    Caching Decorator

    Create a custom decorator for automatic caching:

    // cache.decorator.ts
    

    import { SetMetadata } from '@nestjs/common';

    export const CACHE_KEY = 'cache_key';

    export const CACHE_TTL = 'cache_ttl';

    export const Cache = (key: string, ttl: number = 3600) =>

    SetMetadata(CACHE_KEY, key) && SetMetadata(CACHE_TTL, ttl);

    Session Management

    Implement Redis-based session management:

    // session.service.ts
    

    import { Injectable } from '@nestjs/common';

    import { CacheService } from './cache.service';

    @Injectable()

    export class SessionService {

    constructor(private readonly cacheService: CacheService) {}

    async createSession(userId: string, sessionData: any): Promise {

    const sessionId = this.generateSessionId();

    const sessionKey = session:${sessionId};

    await this.cacheService.set(

    sessionKey,

    JSON.stringify({ userId, ...sessionData }),

    3600 // 1 hour TTL

    );

    return sessionId;

    }

    async getSession(sessionId: string): Promise {

    const sessionKey = session:${sessionId};

    const sessionData = await this.cacheService.get(sessionKey);

    return sessionData ? JSON.parse(sessionData) : null;

    }

    async destroySession(sessionId: string): Promise {

    const sessionKey = session:${sessionId};

    await this.cacheService.del(sessionKey);

    }

    private generateSessionId(): string {

    return Math.random().toString(36).substring(2, 15) +

    Math.random().toString(36).substring(2, 15);

    }

    }

    Real-time Features with Pub/Sub

    Implement pub/sub messaging for real-time features:

    // pubsub.service.ts
    

    import { Injectable } from '@nestjs/common';

    import { RedisService } from '@nestjs/redis';

    import Redis from 'redis';

    @Injectable()

    export class PubSubService {

    private readonly publisher: Redis;

    private readonly subscriber: Redis;

    constructor(private readonly redisService: RedisService) {

    this.publisher = this.redisService.getClient();

    this.subscriber = this.redisService.getClient();

    }

    async publish(channel: string, message: any): Promise {

    await this.publisher.publish(channel, JSON.stringify(message));

    }

    async subscribe(channel: string, callback: (message: any) => void): Promise {

    await this.subscriber.subscribe(channel);

    this.subscriber.on('message', (receivedChannel, message) => {

    if (receivedChannel === channel) {

    callback(JSON.parse(message));

    }

    });

    }

    async unsubscribe(channel: string): Promise {

    await this.subscriber.unsubscribe(channel);

    }

    }

    Best Practices

    1. Connection Pooling

    Configure connection pooling for better performance:

    NestRedisModule.forRoot({
    

    config: {

    host: process.env.REDIS_HOST,

    port: parseInt(process.env.REDIS_PORT),

    maxRetriesPerRequest: 3,

    retryDelayOnFailover: 100,

    lazyConnect: true,

    },

    })

    2. Error Handling

    Implement proper error handling:

    async get(key: string): Promise {
    

    try {

    return await this.redis.get(key);

    } catch (error) {

    console.error('Redis GET error:', error);

    return null;

    }

    }

    3. Key Naming Conventions

    Use consistent key naming patterns:

    const userCacheKey = user:${userId};
    

    const sessionKey = session:${sessionId};

    const tempKey = temp:${requestId};

    Performance Optimization

    1. Pipeline Operations

    Use pipelines for multiple operations:

    async batchSet(keyValuePairs: Array<[string, string]>): Promise {
    

    const pipeline = this.redis.pipeline();

    keyValuePairs.forEach(([key, value]) => {

    pipeline.set(key, value);

    });

    await pipeline.exec();

    }

    2. Memory Optimization

    Configure memory policies:

    # redis.conf
    

    maxmemory 256mb

    maxmemory-policy allkeys-lru

    Monitoring and Debugging

    Health Checks

    Implement Redis health checks:

    @Injectable()
    

    export class RedisHealthIndicator {

    constructor(private readonly cacheService: CacheService) {}

    async isHealthy(): Promise {

    try {

    await this.cacheService.set('health-check', 'ok', 10);

    const result = await this.cacheService.get('health-check');

    return result === 'ok';

    } catch (error) {

    return false;

    }

    }

    }

    Conclusion

    Redis integration with NestJS provides powerful capabilities for building high-performance applications. By implementing proper caching strategies, session management, and real-time features, you can significantly improve your application's scalability and user experience.

    Key takeaways:

  • • Use Redis for caching frequently accessed data
  • • Implement session management for stateful applications
  • • Leverage pub/sub for real-time features
  • • Follow best practices for error handling and monitoring
  • • Optimize performance with pipelines and proper configuration
  • Start integrating Redis into your NestJS applications today and experience the performance benefits firsthand!

    Naveed Ullah

    About Naveed Ullah

    Senior Next.js & NestJS Developer with 5+ years of experience building scalable applications