Caching in NodeJS with Redis
Tags: node, redis, development, cache
Published: 2024-01-26 17:47:38

This blog post will provide a brief explanation on how to use Redis caching to improve server response time, boost performance, and reduce fetch times.

**Step 1:** To run Redis Stack on Windows we need to install Docker.[Download Docker](https://www.docker.com/)

**Step 2:** After installing Docker open the terminal and run the following command:

`docker run -d --name redis-stack -p 6379:6379 -p 8001:8001 redis/redis-stack:latest`

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x4a383ir4a8oath9h526.png)

The command pulls the redis-stack image from the docker hub and runs it.

You can open the Docker Desktop and see the status of the image running.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dxa6qil2jraqw5kc264a.png)

After this, we can visit `http://localhost:8001/` and access the redis stack dashboard:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6zo9gs0slvke0g1p6t6w.png)

Now that the Redis setup is complete, let's move on to the Node.js portion.

We will first look without Redis, then with Redis, to see the difference.

1. Initiate a node package with the following command:
`npm init`

2. Install express and axios package:
`npm install express axios`

3. Find the code below for index.js:

Import the necessary modules:

```
const express = require("express");
const axios = require("axios");
const app = express();
const port = 3000;
```

4. 
```
app.get("/todos", async (req, res) => {
  try {
    // Record the start time
    const startTime = Date.now();

    // Make a GET request to the typicode todos endpoint
    const response = await axios.get(
      "https://jsonplaceholder.typicode.com/todos"
    );

    // Record the end time
    const endTime = Date.now();

    // Calculate the total time taken
    const totalTime = endTime - startTime;

    // Extract todos from the response
    const todos = response.data;

    // Send the todos along with the total time as a JSON response
    res.json({ todos: todos, totaltime: totalTime });
  } catch (error) {
    console.error("Error fetching todos:", error.message);
    res.status(500).json({ error: "Internal Server Error" });
  }
});
```
After running the api in Postman you can see the response.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rbdwvlj10xznotv5xkf9.png)

**With Redis**
Add the following Lines:

```
const Redis = require('ioredis');
const redisClient = new Redis();
```
Initially no data in Redis:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d9ssmr9cd5rv26goy4dz.png)

The complete index.js file:

```
const express = require("express");
const axios = require("axios");
const Redis = require("ioredis");

const app = express();
const port = 3000;

// Create a Redis client
const redisClient = new Redis();

app.get("/todos", async (req, res) => {
  try {
    // Record the start time
    const startTime = Date.now();

    // Check if the response is cached in Redis
    const cachedTodos = await redisClient.get("todos");

    // Record the end time
    const endTime = Date.now();

    if (cachedTodos) {
      // If cached data is found, send it directly
      const parsedTodos = JSON.parse(cachedTodos);

      // Calculate the total time taken for fetching from Redis
      const totalTime = endTime - startTime;

      res.json({ todos: parsedTodos, totalTime, source: "Redis Cache" });
    } else {
      // Make a GET request to the typicode todos endpoint
      const apiStartTime = Date.now();
      const response = await axios.get(
        "https://jsonplaceholder.typicode.com/todos"
      );
      const apiEndTime = Date.now();

      // Calculate the total time taken for fetching from the API
      const apiTotalTime = apiEndTime - apiStartTime;

      // Extract todos from the response
      const todos = response.data;

      // Save the todos to Redis for future use with a TTL of 60 seconds (adjust as needed)
      await redisClient.set("todos", JSON.stringify(todos), "EX", 60);

      // Calculate the total time taken for the entire operation
      const totalTime = apiEndTime - startTime;

      // Send the todos along with the total time as a JSON response
      res.json({ todos, totalTime, apiTotalTime, source: "API" });
    }
  } catch (error) {
    console.error("Error fetching todos:", error.message);
    res.status(500).json({ error: "Internal Server Error" });
  }
});

app.listen(port, () => {
  console.log(`Server is running on http://localhost:${port}`);
});

```

After running the API in postman:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i6tkndnb3twth4ty31bz.png)

You can find that a string in the redis stack browser window.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uw4oz9rmjhrpybaoic98.png)

And wohoo!! After using Redis:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xx02kmghbrw845d7o9l6.png)

The response time has reduced significantly.

So we have pretty much covered how to use Redis as a cache to improve perfomance and efficiency. If you have any doubt I will be more than happy to help. You can mail your queries to 'rajatnayak1582002@gmail.com'.