# Implementing Caching in Node.js Using Redis to Improve WebApp Performance
Time is a valuable factor and a measure of a well-performing web application. The higher the website speed, the higher the performance. Speed has a significant impact on the overall application. It increases the user and developer experience. A web application can be well designed with valuable content, but if the speed is low, people will not wait for it to load.
A study has been done, and it's concluded that most people do not wait for more than 3 seconds for content to load. This is a challenge to websites as they will likely lose potential customers and have low traffic. Caching is the solution to improve your web application performance.
Caching is used in Web development and software development to improve the performance of web applications. It handles web performance issues of managing, storing, and retrieving data. Caching allows frequently accessed data to be stored in an in-memory store or a temporary storage so that data can be retrieved quickly.
Caching greatly reduces the server load time, increases server response time, and reduces the user bounce rate. Also, caching reduces the amount of data that needs to be transferred over a network, thus reducing bandwidth consumption. This leads to an improved user experience.
In this article, we'll explore caching in Node.js applications using Redis. This will help in boosting the performance of Node.js applications. Let's get started.
## Why Caching Data is Important
Caching is a crucial practice for efficient data retrieval. The goal of caching in applications is to speed up the access of data operations to users more than a database and a server can allow. Caching offers several benefits, this includes:
- **Improved performance**- Caching allows data to be stored in a temporary storage. This eliminates the need to retrieve data from its original storage each time a request is made. It reduces latency and improves the response time.
- **Fast response time**- Data sources such as databases and servers require resources to process requests. Caching reduces the number of requests retrieved directly from the primary storage. If the request query is in the cache, the strain on the server is reduced. This frees up more resources, and there is a fast load and response time.
- **Improved app scalability**- Caching enhances scalability. This is because there are a few requests made on the server. The server load is decreased, and the capacity of users who can access the server increases without slowing down the server. The response times remain fast as data is cached frequently. Thus, the servers are not strained.
- **Improved user experience**- Caching reduces the server load time, making it easy for users to access the data they need on applications. A high-performing application leads to a good user experience. Caching improves the user experience.
## Explore Node.js Caching Packages
Caching is a significant technique for improving the performance of Node.js applications. This article will use Redis (Remote Directory Server) as our caching server. Redis is an in-memory data structure used as a database or a cache. In Node.js, we can use caching packages such as Node-cache and Memory-cache to implement caching using Redis.
### Node-cache
[Node-cache](https://github.com/node-cache/node-cache) is a simple and fast Node.js package used for caching. It has `set`, `get`, and `delete` methods and works like other memory caching libraries. The package library can be installed with npm. This is how the module is installed using the `npm` command:
`npm install node-cache --save`
The node-cache module has keys that have a timeout (TTL). After the timeout, keys expire and are deleted from the cache. This is how the module is initialized:
```javascript
const NodeCache = require( "node-cache" );
const myCache = new NodeCache();
```
Here is a basic example of how to use `node-cache` module. After installing and initializing the package in the Node.js application, you can use it like this:
```javascript
// Set a value in the cache with a key and a value
myCache.set('key', 'val');
// Get a value from the cache
const cachedValue = myCache.get('key');
console.log('Cached Value:', cachedValue); // Output: Cached Value: val
// Check if a key exists in the cache
const keyExists = myCache.has('key');
console.log('Key Exists:', keyExists); // Output: Key Exists: true
// Remove a key from the cache
const removed = myCache.del('key');
console.log('Key Removed:', removed); // Output: Key Removed: true
// Check again if the key exists
const keyExistsNow = myCache.has('key');
console.log('Key Exists Now:', keyExistsNow); // Output: Key Exists Now: false
```
In the code snippet above, `node-cache` module creates an in-memory cache(`myCache`). We can set, get, check if values exist, and delete values from the cache. The values are stored in a cache.
### Memory-cache
[Memory-cache](https://www.npmjs.com/package/memory-cache-node) is a Node.js caching package that is fast and safe for caching data. The package stores, retrieves, checks if data exists, and removes data from the memory cache. The `memory-cache` is installed using the `npm` command:
`npm install --save memory-cache-node`
Here is an example of how to use `memory-cache` module:
```javascript
const cache = require('memory-cache');
// Set data in the cache
cache.put('key', 'val', 10); // 10 seconds expiration time
// Retrieve data from the cache
const cachedData = cache.get('key');
if (cachedData) {
console.log('Fetched from cache:', cachedData);
} else {
console.log('Data not found in cache. Fetching from the source.');
// Fetch data from the source (e.g., database or API)
// Once fetched, store it in the cache for future use
cache.put('key', 'fetchedData', 10);
}
```
In the code above, `memory-cache` package is used to store data in a key in the memory. Data in the cache is set to have 10 seconds expiry time. Data is removed from the cache after expiry. If data is not found in the cache, it's fetched from its primary source and stored again in the cache awaiting requests.
## Implementing Node.js Caching Using Redis
In this section, we will implement caching in Node.js using Redis. Redis is an in-memory data store that implements caching in Node.js applications. Redis is a perfect choice for applications that store and retrieve large amounts of data. It is particularly suitable for web applications such as e-commerce and large websites with huge data and traffic.
Redis, being an in-memory database, enables users to access data operations faster than any other database. This makes Redis the perfect data store for caching in large applications. The goal of caching is to improve the performance of these applications.
In this section, we'll look at how to use Redis to cache data from an external API on a simple Node.js application. We'll need to install Redis on our Windows, Linux, and Mac operating systems to get started.
### Step 1: Installing Redis Server
Download the installer from the [official Redis website](https://redis.io/download/) to begin the installation. Follow your operating system installation instructions to successfully install the server.
In this tutorial, we will install Redis on a Windows operating system. Download the Windows Redis installer from this [Github Repository](https://github.com/microsoftarchive/redis/releases). Run the installer to install Redis on your computer. After installing Redis, open the command prompt and run the command `redis-cli` to start the server.

Run the `ping` command to ensure the server is running right. The `ping` command pings the server to confirm its execution, and the PONG response in the command line (CLI) means the server is working well.
### Step 2: Setting up the project
To set up the project, proceed to the project directory and initialize `npm` with this command:
```bash
npm init -y
```
Once the initialization is complete, the next step is to install the packages we will use in the tutorial. Implementing caching in Node.js will require these packages:
- [`node-redis`](https://www.npmjs.com/package/redis): For connecting to the redis server running on local machine. The package allow us to store and access data in Redis.
- [`express`](https://www.npmjs.com/package/express): For setting up the web server.
- [`dotenv`](https://www.npmjs.com/package/dotenv): For loading environment variables.
- [`nodemon`](https://www.npmjs.com/package/nodemon): For running the development server.
Install the packages by running the following commands:
```bash
npm i node-redis express dotenv
```
```bash
npm i --save-dev nodemon
```
On the project directory, create a new file and name it `app.js`. The file will host the application logic of starting a HTTP server and processing incoming requests.
To set up the HTTP server, add the following code in `app.js` to create an Express server:
```javascript
//Import the express package
const express = require('express');
//Initialize the application
const app = express();
//Accept payload data
app.use(express.json());
//Set up the routes
app.get("/", (req, res) => {
return res.send({
success: true,
message: "Hello World",
});
});
//Start the application on PORT 3000
app.listen(3000, () => console.log("App started and running on PORT 3000"));
```
The code above creates an express server. We first imported `express` and then set up the `app` variable as an instance of `express`. We used `json` to enable the app transmit data in the application from the server. Finally, we used the module `listen()` to start the application on PORT `3000`.
On the `package.json` file under the `scripts` section, add a script to start the server as below:
```json
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "node app.js"
},
```
Start the application using:
```bash
npm run dev
```
### Set up a Redis middleware
In this tutorial, we will be consuming Animals API from [API Ninjas](https://api-ninjas.com/). That's where the data to be cached will be gotten. If you do not have an account there, create one before proceeding. Once you have created the account, save your API Key in a `.env` file in the project root directory:
```bash
API_KEY = your_api_key
```
In the project root directory, create a directory named `middlewares`. Inside the `middlewares` directory, create a file named `redis.js` file.
In the `redis.js` file, import the `redis` and `dotnev` packages.
```javascript
const redis = require('redis');
require("dotenv").config();
```
Define the middleware for fetching from redis or API:
```javascript
exports.fetchAnimal = async (req, res) => {
try {
let { name } = req.body; // get the name of the animal from payload
if (name) {
// set up connections
const RedisClient = redis.createClient({
host: "127.0.0.1",
port: 6379,
});
// connect to redis
let conn = await RedisClient.connect();
// check if there is a saved record on redis.
let animal = await conn.get(name);
// if there is, show it
if (animal) {
return res.json({
success: true,
message: JSON.parse(animal),
from_cache: true,
});
} else {
// send request to animals api
let response = await fetch(
"https://api.api-ninjas.com/v1/animals?name=" + name,
{
method: "GET",
headers: {
"X-Api-Key": process.env.API_KEY,
},
},
);
response = await response.json();
// set the cache and it's duration (5 mins)
conn.setEx(name, 300, JSON.stringify(response));
// return the response
return res.json({
success: true,
message: response,
from_cache: false,
});
}
} else {
return res.json({
success: false,
message: "Animal name is required",
});
}
} catch (error) {
return res.json({
success: false,
message: "An error occurred fetching animal",
error,
});
}
};
```
The code above sets up a connection using `redis.createClient()`. The `redis.createClient` function allows you to create the Redis client. The function uses `127.0.0.1` as the host and `6379` as the port. When creating a Redis client, specify the host and port the server is running. Hence, the client can easily connect to the server.
The code sends a request to the Animals API, sets it to the cache, and then sends it to the client. When data is requested again, the code checks if the record exists in the cache and sends the data to the client from there.
In this section, import the middleware in `app.js` file:
```javascript
const { fetchAnimal } = require("./middlewares/redis");
```
Modify the default route we had set up earlier, and replace the snippet with the code below:
```javascript
app.post("/", fetchAnimal);
```
### Step 3: Running the application
Ensure your development server is still running from your terminal:
```bash
npm run dev
```
From your postman, send a `POST` request to http://localhost:3000/. In the payload, add an object similar to the code below then send a request.
```json
{
"name": "fox" // feel free to replace it with the name of animal you like
}
```
The first request will have `from_cache` set to false, and the other will have `from_cache` true until the five minutes for the cache duration are over. Wait for the response and check the time taken to get the response. Saving data in a cache helps to reduce the response time and the overall network bandwidth used.
## Wrapping Up
Congratulations, we came to the end of this article. Caching is great for improving the performance of applications. Improved app performance leads to a good user experience. Caching data enables users to access data faster and with less network bandwidth.
In this article, we learned how to implement caching in Node.js to improve application performance. Also, we learned why it's crucial to use Redis when caching application data.
Happy learning!