What is Redis and How to Use it with Nest.JS

Today we will talk about Redis. A very powerful and easy database to use. It is very popular for caching.

Prerequisites

  • Basic Understanding of Caching

  • Experience in NestJS

The problem

We at our company are building a property management solution where we have to maintain many users and they can have various permissions based on their role.

So after each successful login client makes a request to get the user profile details along with the permissions for them. As the query is very complex and requires the joining of multiple tables it took a long time to load.

And the users have to wait a long time before seeing anything on their screen which is a very bad user experience.

The Solution

So after digging through some possible solutions, we found that Caching is the answer for us. Because of 2 reasons mainly

  • This API is called very frequently.

  • Users' permissions don’t change so frequently

So after some digging, it was clear that Redis might be the best way to go for us. And Redis is a good choice for caching

So Why Redis?

  • Redis is really really fast. It was written in C so it’s really efficient.

  • It’s very easy to use. It’s almost like our browser's local storage but way more powerful. You just set some data with a key and get it back with that same key.

  • All the major languages/frameworks have support for Redis.

  • It’s really popular and used by many major companies so stability is not an issue at all

NestJS makes it really easy to use Redis. Now we will see how to use it.

Step 1. Install dependencies

Install the following dependencies

yarn add cache-manager cache-manager-redis-store

Step 2. Add Caching Module

Then create a module for caching

nest g module redis-cache

Then add the following code to your redis-cache.module.ts file

    import { CacheModule, Module } from '@nestjs/common';
    import { RedisCacheService } from './redis-cache.service';
    import { ConfigModule, ConfigService } from '@nestjs/config';
    import * as redisStore from 'cache-manager-redis-store';
    
    @Module({
        imports: [
            CacheModule.*registerAsync*({
                imports: [ConfigModule],
                inject: [ConfigService],
                useFactory: async (configService: ConfigService) => ({
                    store: redisStore,
                    host: configService.get('REDIS_HOST'),
                    port: configService.get('REDIS_PORT'),
                    ttl: configService.get('CACHE_TTL'),
                    max: configService.get('MAX_ITEM_IN_CACHE')
                })
            })
        ],
        providers: [RedisCacheService],
        exports: [RedisCacheService]
    })
    export class RedisCacheModule {}

A few things to note here…

REDIS_HOST : It specifies the host of our Redis database (ex: localhost)

REDIS_PORT : The default port value is 6479

CACHE_TTL : It specifies the amount of time in seconds before a value is invalidated

MAX_ITEM_IN_CACHE : It specifies the maximum number of items that should be kept in the cache.

Step 3. Create a Service

Create a new service for caching

nest g service redis-cache

Then add the following code in redis-cache.service.ts file

    import { ***CACHE_MANAGER***, Inject, Injectable } from '@nestjs/common';
    import { Cache } from 'cache-manager';
    
    @Injectable()
    export class SomeService {
        constructor(@Inject(***CACHE_MANAGER***) private readonly cache: Cache) {}
    
        async get(key): Promise<any> {
            return await this.cache.get(key);
        }
    
        async set(key, value) {
            await this.cache.set(key, value, 1000);
        }
    
        async reset() {
            await this.cache.reset();
        }
    
        async del(key) {
            await this.cache.del(key);
        }
    }

These are utility functions to work with Cache.

Step 4. Use Caching Service

Inside any service, you can now import the RedisCacheModule into a different module.

    @Module({
        imports: [RedisCacheModule],
        controllers: [UserController],
        providers: [UserService],
        exports: [UserService]
    })
    export class SomeModule {}

Then use it in any service inside that module

    @Injectable()
    export class UserService {
        constructor(private cacheManager: RedisCacheService) {}

       async setSomeValue(KEY , value){
          await this.cacheManager.set(KEY , value);
       }

       async getSomeValue(KEY){
          await this.cacheManager.get(KEY);
       }

    }

Bonus: Dockerize the whole application

If you run your application now you will run into an error because you don’t have the Redis database up and running. You have two choice

  • Install and run Redis on your local machine

  • Use docker to pull the Redis image from the docker hub.

We will see how to do the later now.

The main Dockerfile is typical for any nodeJS application

    FROM node:12-alpine
    WORKDIR /app
    ADD package.json /app/package.json
    RUN yarn install
    ADD . /app
    EXPOSE 3000
    CMD ["yarn", "start"]

We have to add another and the docker-compose.yml file

version: '3'
services:
  redis:
    image: 'redis:alpine'
  node-app:
    build: .
    ports:
      - "3000:3000"

Here we are pulling the official Redis image from the docker hub and run it so that our application can access it. > If you run Redis from the docker image you have to change the REDIS_HOST value(used in step 2) to redis (used in docker-compose file)

Now you should be more comfortable about using Redis in your next project. It’s really a very useful tool to keep under your developer's belt.

That’s it for today. Happy Coding! :D

Get in touch with me via LinkedIn


Share this post


Read more articles...

team

Dockerizing a basic Node.js/Nest.js application

team

Getting Started with Nextjs

team

Improve SEO in NextJS

team

Handle Docker Images Like A Pro

Profile Image

Who I am

Hi, I amMohammad Faisal, A full-stack software engineer @Cruise , working remotely from a small but beautiful country named Bangladesh.

I am most experienced inReactJS,NodeJS andAWS

Buy Me a Coffee Widget