What is Redis and How to Use it with Nest.JS
Tags: react, javascript, programming, database
Published: 2023-05-13 18:00:00

_**To read more articles like this, [visit my blog](https://www.mdfaisal.com/blog)**_


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

```js
yarn add cache-manager cache-manager-redis-store
```

### Step 2. Add Caching Module

Then create a module for caching

```js
nest g module redis-cache
```

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

```js
    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

```js
nest g service redis-cache
```

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

```js
    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.

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

Then use it in any service inside that module

```js
    @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

```js
    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

```js
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](https://www.linkedin.com/in/56faisal/) or my [Personal Website](https://www.mdfaisal.com/).**