How to use ConfigCat with Redis
Tags: featuremanagement, featureflags, redis, configcat
Published: 2023-06-07 19:51:18

Ever since the dawn of feature releases, feature flags have become the de facto standard for managing and controlling features in software applications. Many software development methodologies these days such as agile, are heavily focused on releasing continuous updates and features. In addition, a few companies have based their entire business around serving clients a cloud-based feature flagging solution. But in limited bandwidth situations or when you need to optimize the performance of your client-facing applications making API requests may not be ideal. This can be handled by implementing a process called caching with the help of a popular tool called [Redis](https://link-to-redis).

<!-- truncate -->

## What are feature flags?

A feature flag can be described as a light switch for features. It holds a boolean value, that when set to true, the feature it controls can be displayed to the user and otherwise hidden.

The awesome thing about feature flagging is that it can be applied to a wide range of [programming languages and frameworks](https://github.com/orgs/configcat-labs/repositories). And because of its flexible nature, it can be used alongside other technologies. Let's look at how it can be implemented with a [Redis cache](https://redis.io/) to see how it works.

## Pre-requisites

- A code editor (e.g. [Visual Studio Code](https://code.visualstudio.com/))
- [NodeJS](https://nodejs.org/en/) (version 16 or higher)
- Basic [Node.js](https://nodejs.org/en) and [Redis](https://redis.io/) knowledge.
- Have [Docker](https://www.docker.com/) installed on your computer.

To help you follow through with me, I've created a Node.js sample app that you can clone from the following [link](https://github.com/configcat-labs/configcat-with-redis-sample/tree/starter-cod). Later on, we'll cover how to set it up.

## Adding a feature flag

**1.** To get started, sign up for a [free ConfigCat account](https://app.configcat.com/signup).

**2.** In your dashboard, create a feature flag with the following information:

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

## Creating the Redis cache client

**3.** From the [`starter-code`](https://github.com/configcat-labs/configcat-with-redis-sample/tree/starter-code) branch, open the file called `configcat-redis-cache.js` and add the following functions:

```js
// ...

function configcatRedisCache(redisClientOptions) {

  this.isRedisAvailable = false;
  this.cacheClient = redis.createClient(redisClientOptions);

  this.cacheClient.connect();

  this.cacheClient.on("connect", () => {
    console.log("Connected to Redis");
    this.isRedisAvailable = true;
  });

  this.cacheClient.on("error", (error) => {
    console.log(`Redis error: ${error}`);
    this.isRedisAvailable = false;
  });

  this.lastCacheItems = {};
}

configcatRedisCache.prototype.get = async function (key) {
  if (!this.isRedisAvailable) {
    return this.lastCacheItems[key];
  }

  try {
    const getAsync = util
      .promisify(this.cacheClient.get)
      .bind(this.cacheClient);

    return JSON.parse(await getAsync(key));
  } catch (error) {
    console.error(`Cache read failed! \n ${error}`);
    return this.lastCacheItems[key];
  }
};

configcatRedisCache.prototype.set = async function (key, item) {
  this.lastCacheItems[key] = item;

  try {
    const setAsync = util
      .promisify(this.cacheClient.set)
      .bind(this.cacheClient);

    await setAsync(key, JSON.stringify(item));
  } catch (error) {
    console.error(`Cache write failed! \n ${error}`);
  }
};

// ...

```

Here's what each function does:

- **`configcatRedisCache`** - Takes the client options as its parameter and sets up a connection to the docker Redis instance.

- **`configcatRedisCache.prototype.get`** - Uses the provided `key` to obtain the cached item from Redis.

- **`configcatRedisCache.prototype.set`** - Takes the `key` and `item` as parameters. Puts the `item` into the redis cache that can be later accessed using the `key`.

**4.** Open the `index.js` file and add the following code:

```js
// ...
const redisOptions = { host: "localhost", port: 6379 };

const configCatClient = configcat.getClient("0yDbCLmNK0qIUakB2LFJDA/u0Z5j4oDjkuHKOVJkIo9Dw", configcat.PollingMode.AutoPoll, 
  {
    cache: configcatRedisCache(redisOptions)
  }
);

setInterval(() => {
  configCatClient.getValueAsync("isMyAwesomeFeatureEnabled", false).then(value => {
    console.log(`${new Date().toTimeString()} isMyAwesomeFeatureEnabled: ${value}`);
  });
}, 5000);
```

Here's what the code is doing:

- The configuration required to establish a connection to the Redis docker instance was saved to the `redisOptions` variable.

- That variable was then used in the `configcat.getClient` method passed as an argument to set up the `cache` property.

- The `setInterval` function runs every 5 seconds to fetch the value of the feature flag, but instead of reaching out to [ConfigCat](https://configcat.com), it obtains the value from the Redis cache and logs the result with the date to the console.

You can find the complete code for the `index.js` file [here](https://github.com/configcat-labs/configcat-with-redis-sample/blob/master/index.js). If you're curious about learning more about using a custom cache with [ConfigCat](https://configcat.com) as we did, refer to [this documentation](https://configcat.com/docs/sdk-reference/node/#using-custom-cache-implementation).

With the code in place, let's look at how we can run the sample app to ensure it works.

## Running the sample app

**1.** Clone the [GitHub repository](https://github.com/configcat-labs/configcat-with-redis-sample)

**2.** Run the following commands to install the required node packages:

```sh
npm install
```

The `configcat-node` and `redis` npm packages will also be installed using this command. The `configcat-node` package will be used as a client to connect to and pull the feature flag status from your [ConfigCat dashboard](https://app.configcat.com). `redis` will be used similarly and would connect to a local docker instance of Redis.

**3.** Using docker, pull the latest Redis docker image and run the container:

```sh
docker pull redis
```

```sh
docker run --name container-redis -p 6379:6379 -d redis
```

**4.** Start the node application with the following command:

```sh
npm start
```

You should see the following output logged to your terminal every 5 seconds:

```sh
> configcat-with-redis-sample@1.0.0 start
> node index.js

Connected to Redis
17:56:55 GMT-0300 (French Guiana Time) isMyAwesomeFeatureEnabled: false
17:57:00 GMT-0300 (French Guiana Time) isMyAwesomeFeatureEnabled: false
17:57:05 GMT-0300 (French Guiana Time) isMyAwesomeFeatureEnabled: false
17:57:10 GMT-0300 (French Guiana Time) isMyAwesomeFeatureEnabled: false
17:57:15 GMT-0300 (French Guiana Time) isMyAwesomeFeatureEnabled: false
17:57:20 GMT-0300 (French Guiana Time) isMyAwesomeFeatureEnabled: false
```

Toggling on or off the feature flag within your [ConfigCat dashboard](https://app.configcat.com) will force the cache to refresh. As a result, The new value will be pulled from [ConfigCat](https://configcat.com) to replace the existing value in the cache.

## Final thoughts

If you're planning on cutting back or saving bandwidth utilization and optimizing for better performance on the client side then a caching solution like Redis can help. And, as we've seen from the code examples, Redis integrates quite easily with [ConfigCat](https://configcat.com). With a caching solution in place, you can supercharge the way you do standard feature releases, canary deployments, and A/B testing. Besides Node.js, ConfigCat also supports [many languages and frameworks](https://github.com/orgs/configcat-labs/repositories) and provides [SDKs](https://configcat.com/docs/sdk-reference/overview/) for easy configuration.

## Stay updated

For more posts like this and other announcements, follow ConfigCat on [Twitter](https://twitter.com/configcat), [Facebook](https://www.facebook.com/configcat), [LinkedIn](https://www.linkedin.com/company/configcat/), and [GitHub](https://github.com/configcat).