Set up cache with Redis in Node.js

ยท

4 min read

๐Ÿ˜ถ
Although the package used in this article still works, I suggest you to switch to something like Keyv which is more scalable and multi-provider.

It's 2020 and having a cache it's today a required part of your stack. For example, you could cache your database response for X time (or until a new entry comes in) to stop doing a query (or more!) for every request.

Recently I had to implement it in Node.js and I've chosen to go with Redis. I was looking for a decent but simple-to-use library and I didn't find so much, so I decided to write my own: Redache.

Let's see how to implement it!

Installation

To install the library, just run from your terminal yarn add redache or, if you use npm: npm i redache --save.

Then, of course, you have to include it in your project. If you use ES6 features, you can use import:

import Redache from 'redache';

// ...

Otherwise, you can go with the CommonJS way:

const Redache = require('redache');

// ...

The last but not least step is to initialize it. This is a minimal configuration, but you can check out all the available parameters in the Redis official package: github.com/NodeRedis/node_redis#options-obj..

const cache = new Redache({
    host: '127.0.0.1',
    port: 6379,
    password: 'foobar',
});

Save values

I wanted to keep the library as easy as possible. To store a value, you just have to call the .set() method providing a key, a value and a TTL (expiration time).
Usually with these libraries, you have to specify the TTL as a number representing the seconds, but guess what? I didn't want to make your life harder, but easier, so... You can choose between four methods to specify your expiration and the first one si my favorite.

1. Human readable TTL Just pass a format like number TIME_UNIT to set the expiration. It uses moment behind the scenes to "decode" it, so TIME_UNIT can be something like days, day, d, month and so on.

// It expires in 5 hours
await cache.set('key', 'value', '5 hours');

2. Date instance If you're more "old school" and you have a Date instance, don't worry, we accept it as well.

// It expires the 1st Jan 2050
await cache.set('key', 'value', new Date(2050, 1, 1));

3. moment instance We said it uses moment under the hood, so of course you can provide a moment object.

// It expires in 1 month
await cache.set('key', 'value', moment().add(1, 'month'));

4. Seconds And finally, if you're a real boss, you can pass a number representing the seconds. I don't know why you should, but ehy, up to you!

// It expires in 3600 seconds -> 1 hour
await cache.set('key', 'value', 3600);

Object(s) and Array(s)

Most of the time you want to save a whole object or array, but the native Redis functions won't let you do that. But we do. Just pass your desired variable and the library will take care of JSON serializing and deserializing it.

Retrieve values

After you saved your value you may desire (or may not?) to retrieve it.

const value = await cache.get('key');

As we said, Redache accepts objects and arrays too, let's see how:

await cache.set('key', { foo: 'bar' }, '1 hour');

// Retrieve it
// It will be: { foo: 'bar' } but stored as '{"foo":"bar"}'
const value = await cache.get('key');

Easy, right? Now let's say that you want to store a value if a key is not found (or expired) on Redis, you would write something like:

let value = await cache.get('key');
if (value === null) {
    value = 'my fallback';
    await cache.set('key', 'my fallback', '1 day');
}

NOOOOOOO!! The library can manage this for you, in just one line! In fact, the 2nd and 3rd arguments of .get() are, respectively, the fallback value and the fallback TTL.

const value = await cache.get('key', 'my fallback', '1 day');

Isn't it more simple? The fallback value accepts as well a function (async too):

const value = await cache.get('key', () => 'my fallback', '1 day');

// Async example
const value = await cache.get('key', () => Promise.resolve('my fallback'), '1day ');

Delete a key

Like alchemy, you can create and destroy (yes, I recently saw Fullmetal Alchemist). Just invoke .forget() method specifying your key.

// Save a record
await cache.set('key', 'value', '1 day');

// It returns `value`
const value = await cache.get('key');

// Now let's remove it
await cache.forget('key');

// It will return null now, because we removed it
const valueAgain = cache.get('key');

Conclusion

That's it! I hope this library can help you as much as it helped me and don't forget to leave a star!

Star

ย