Improving NestJS Speed with Redis Caching Solutions

Improving NestJS Speed with Redis Caching Solutions

Boost Your NestJS App Using Redis Cache

Caching is a powerful technique to speed up your applications, making them more responsive and efficient. In this post, I'll walk you through how to integrate Redis cache into a NestJS application. Redis is an in-memory data structure store that can be used as a database, cache, and message broker. By the end of this tutorial, you'll have a solid understanding of how to set up and use Redis in your NestJS projects.

Why Use Redis?

Redis offers several benefits for caching:

  • Speed: Since Redis is an in-memory store, it's incredibly fast.

  • Persistence: It supports data persistence, allowing you to save snapshots of your data to disk.

  • Data Structures: Redis supports various data structures such as strings, hashes, lists, sets, and more.

  • Scalability: Redis can be scaled easily to handle large amounts of data and high request rates.

Setting Up Redis

Before we dive into the code, make sure you have Redis installed and running. You can either download Redis from its official website or use a Docker container for a quick setup:

docker run --name redis -p 6379:6379 -d redis

Setting Up NestJS

If you don't already have a NestJS project, let's create a new one:

nest new redis-cache-example
cd redis-cache-example

Installing Dependencies

Next, we'll need to install some packages for Redis and caching:

npm install cache-manager cache-manager-redis-store redis

Integrating Redis with NestJS

1. Configure Cache Module

First, we need to configure the CacheModule in our app.module.ts file to use Redis:

import { Module, CacheModule } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import * as redisStore from 'cache-manager-redis-store';

@Module({
  imports: [
    CacheModule.register({
      store: redisStore,
      host: 'localhost', // Redis server host
      port: 6379,        // Redis server port
      ttl: 600,          // Time to live (seconds)
    }),
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

Here, we configure the CacheModule to use Redis as our cache store, specifying the host and port where Redis is running. We also set a time-to-live (TTL) of 600 seconds for cached data.

2. Using Cache in Services

Now, let's use the cache in our service. We'll inject the cache manager and use it to cache data. Here's an example in app.service.ts:

import { Injectable, Inject } from '@nestjs/common';
import { CACHE_MANAGER } from '@nestjs/cache-manager';
import { Cache } from 'cache-manager';

@Injectable()
export class AppService {
  constructor(@Inject(CACHE_MANAGER) private cacheManager: Cache) {}

  async getHello(): Promise<string> {
    const cacheKey = 'hello_cache';
    let cachedData = await this.cacheManager.get<string>(cacheKey);

    if (!cachedData) {
      cachedData = 'Hello World!';
      await this.cacheManager.set(cacheKey, cachedData, { ttl: 600 }); // Cache for 10 minutes
    }

    return cachedData;
  }
}

In this service, we first try to get the cached data using cacheManager.get. If there's no cached data, we set it using cacheManager.set.

3. Handling Cache in Controllers

Next, we use this service method in our controller. Here’s how our app.controller.ts looks:

import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Get()
  async getHello(): Promise<string> {
    return this.appService.getHello();
  }
}

This controller simply calls the getHello method from our service to return the cached or newly set data.

Advanced Caching Techniques

Caching Method Results

NestJS provides a @Cacheable decorator to cache method results effortlessly. Here’s how you can use it:

import { Injectable } from '@nestjs/common';
import { Cacheable } from 'nestjs-cacheable';

@Injectable()
export class AppService {
  @Cacheable({ ttl: 600 }) // Cache for 10 minutes
  async getHello(): Promise<string> {
    return 'Hello World!';
  }
}

With the @Cacheable decorator, the method result is automatically cached, saving you from manually handling cache logic.

Invalidating Cache

Sometimes, you might need to invalidate the cache when the underlying data changes. Use cacheManager.del to remove cached data. Here’s an example:

import { Injectable, Inject, CACHE_MANAGER } from '@nestjs/common';
import { Cache } from 'cache-manager';

@Injectable()
export class AppService {
  constructor(@Inject(CACHE_MANAGER) private cacheManager: Cache) {}

  async updateHello(newData: string): Promise<void> {
    const cacheKey = 'hello_cache';
    await this.cacheManager.del(cacheKey);
    // Update the data in your database or other persistent storage
  }
}

In this example, when updateHello is called, the cache for hello_cache is invalidated, ensuring that subsequent requests fetch the latest data.

Conclusion
Integrating Redis cache into your NestJS application can significantly enhance performance and scalability. In this blog post, we covered the basics of setting up Redis, configuring the CacheModule in NestJS, and implementing caching in services and controllers. By leveraging these techniques, you can make your NestJS applications more responsive and provide a better user experience.

Happy coding!