Caching with Redis: Node.js Example

Published Mar 14, 2018Last updated Apr 23, 2018
Caching with Redis: Node.js Example

This article is the second in my Intro to Redis and Caching series. If you have no idea what Caching is or what Redis is, please read my Introduction to Caching and Redis post before proceeding.

Now that you have an understanding of what Caching and Redis are, let's build a very basic project that implements caching using Redis. I will assume a beginner-level understanding of Node.js with Express.

Project Info
We will call this project Wikipedia Article Getter and it will allow users to query the Wikipedia API from our endpoint.

Prerequisite
Ensure you have Node.js installed on your computer, then open your Terminal (Mac OS) or Command Prompt (Windows users).

Install Redis on your machine
If you an OSX user, you can install using the command below. For other platforms, please follow the guide on https://redis.io/download.

brew install redis

Create a new directory

mkdir redis-cache

Navigate to the new directory

cd redis-cache

Generate a package.json file

npm init --force

--force tells npm to use the default options while generating the package.json so you are not asked any questions.

After running the command above, you should have a package.json file in the redis-cache directory.

Create a file server.js in the directory.

Create a server.js file
The directory should look like this with two files in it;

redis-cache [directory]
- server.js [file]
- package.json [file]

We will use the following npm packages in this project:
Axios to make HTTP requests.
Express for routing.
Redis as Node.js redis client.
Response-time to record response time in the response header.

Install the modules

npm install --save axios express redis response-time

Redis Installed? Update Project Code
Now that you have Redis installed, add the following code to the server.js file.

// Import the installed modules.
const express = require('express');
const responseTime = require('response-time')
const axios = require('axios');
const redis = require('redis');

const app = express();

// create and connect redis client to local instance.
const client = redis.createClient();

// Print redis errors to the console
client.on('error', (err) => {
  console.log("Error " + err);
});

// use response-time as a middleware
app.use(responseTime());


// create an api/search route
app.get('/api/search', (req, res) => {
  // Extract the query from url and trim trailing spaces
  const query = (req.query.query).trim();
  // Build the Wikipedia API url
  const searchUrl = `https://en.wikipedia.org/w/api.php?action=parse&format=json&section=0&page=${query}`;

  // Try fetching the result from Redis first in case we have it cached
  return client.get(`wikipedia:${query}`, (err, result) => {
    // If that key exist in Redis store
    if (result) {
      const resultJSON = JSON.parse(result);
      return res.status(200).json(resultJSON);
    } else { // Key does not exist in Redis store
      // Fetch directly from Wikipedia API
      return axios.get(searchUrl)
        .then(response => {
          const responseJSON = response.data;
          // Save the Wikipedia API response in Redis store
          client.setex(`wikipedia:${query}`, 3600, JSON.stringify({ source: 'Redis Cache', ...responseJSON, }));
          // Send JSON response to client
          return res.status(200).json({ source: 'Wikipedia API', ...responseJSON, });
        })
        .catch(err => {
          return res.json(err);
        });
    }
  });
});

app.listen(3000, () => {
  console.log('Server listening on port: ', 3000);
});

Run the app

node app.js

Point your browser to localhost:3000/api/search?query=Nigeria.
You can replace the Nigeria with any word of your choice.

Verifying Performance/Speed
Open Chrome Developer Tools > Network > /api/search?query=Nigeria

Take note of the X-Response-Time fields in the two images below.

First Request
Screen Shot 2018-03-04 at 08.24.47.png

Second Request:
Here is the response header for the second request
Screen Shot 2018-03-04 at 08.25.05.png

The first request took 2739 milliseconds while the second one only took 6 milliseconds, a difference of 2733 milliseconds!

Confused?
Here is the request-response flow to help you understand what goes on in the /api/search route hander:

  1. User requests for article
  2. We look inside the Redis store to see the articles that have been cached previously
    • If true, we serve the cached version to the client.
    • Otherwise, we fetch the article from the Wikipedia API
      • We cache the response from the API in Redis for an hour (3600 seconds)
      • We send a response to the user.

More Information?
If you have questions, kindly leave a comment. Remember to share the article if you find it informative.

Discover and read more posts from Olawale
get started