Adding Redis To Craft CMS

Posted: 12th Jan 2020

Adding Redis to a Craft site can have a big impact on both its performance and scalability, but what is Redis, how do we integrate it with Craft and what does Craft actually store in there?

What is Redis?

Redis is a data storage application which allows us to store and retrieve data. This sounds a lot like a database, but Redis is a particular type of data store called a Key-Value (KV) store. This type of data store is designed with a limited scope and simply holds all of your data (the Value) along with an address or name for that data (the Key). By keeping the scope of the storage mechanism limited, Redis is able to offer a resource efficient, very fast method of storing and retrieving your data.

Redis is also an in-memory data store. It holds everything you've given to it in memory so that it can be accessed as quickly as possible - much faster than looking up information from a disk. The down-side of in-memory storage is that if the memory is lost due to an error or the system being restarted all the current data held there is lost.

Redis compensates for this by writing its data to the disk on a configurable schedule (normally every few seconds). This way it's able to recover the majority of its data in case of an accident, but you must plan for the possibility of it loosing some of its state if anything goes wrong.

What Does Craft CMS Store in Redis?

Because of Redis's KV, in-memory architecture, it is often used to store cache data. Cache data can normally be recreated if it is lost so we don't need to be too concerned about losing small amounts of it. It also tends to exist in isolation, without requiring the storage of any relationships to other data.

In a normal Craft installation, all cache data is stored in files on the local disk. This can become a problem if the cache data is particularly large or is accessed very frequently as it increases the chance of the disk drive becoming a bottleneck for page load times.

We can therefore tell Craft to make use of Redis for all of its temporary cache data. Once configured this cache data will include:

  • Available updates
  • Plugin store data
  • GraphQL query results
  • Some bits of data from the Craft Net API including license information
  • Project Config modification timestamps
  • Any data which is explicitly cached by plugins you have installed

This is a surprisingly short list and has one significant omission: {% cache %} tag template content. (See Update July 2020 for Craft 3.5 news on this)

Somewhat counter-intuitively, Craft does not store {% cache %} tag data in its configured cache store. Instead it is inserted into the database.

There's a reason for this which has its pros and cons. Craft allows {% cache %} tag results to be invalidated by linking it to the entries that were queried during its production. This relationship between cache data and entries makes it more difficult for the cache to be efficiently stored in a simple KV store. Read Brandon's explanation here.

Update July 2020

Craft 3.5 now stores template caches and associated tags in its data cache! Info here. This is a big win for performance and scalability. The relationships between entries and the caches in which they appear is still being maintained but this is being done in a more generic, but performant way.

This new caching method will work with any cache storage solution, but could potentially cause issues with the default filesystem based cache if you're running Craft on multiple load balanced servers. This makes the use of a well configured Redis sever even more important for Craft 3.5 projects.

Anything Else We Can Put In There?

Well yes actually. As well as offering increased speed of access, Redis provides Craft with a central store of cache data removed from the filesystem wherever Craft is running. This allows us to have multiple instances of our Craft application all running on different servers but sharing a single, external cache.

This is more efficient as it prevents each of our instances from having to generate their own copy of all the cache entries. More importantly, it also ensures that all instances are using the same data.

Often we can tolerate a little difference between cache data, but one thing that we can't tolerate differences in is PHP session information.

Normally PHP would store PHP session information on the local filesystem. If we're running multiple instances of Craft side-by-side this will result in each instance generating its own session data. You could be logged into the control panel on one instance and not on another! Leading to very upsetting results.

To rectify this we can push all PHP session information out to Redis which allows all of our instances to share the same data whilst still accessing it quickly.

How Do We Set This Up?

To store all of Craft's cache data in Redis, you need to make sure you have the yiisoft/yii2-redis package added to your composer.json file and that it has been installed. Then edit config/app.php and update your components section to look like the following:

<?php
return [
    'components' => [
        'redis' => [
            'class' => yii\redis\Connection::class,
            'hostname' => getenv('REDIS_HOST'),
            'port' => getenv('REDIS_PORT'),
            'password' => getenv('REDIS_PASSWORD'),
        ],
        'cache' => [
            'class' => yii\redis\Cache::class,
            'defaultDuration' => 86400,
            'keyPrefix' => getenv('REDIS_KEY_PREFIX'),
        ],
    ],
];

Then simply add environment variables for:

  • REDIS_HOST
  • REDIS_PORT
  • REDIS_PASSWORD
  • REDIS_KEY_PREFIX

Moving the PHP session data into Redis requires adding an additional element to the components array:

<?php
return [
    'components' => [
        'redis' => [
            'class' => yii\redis\Connection::class,
            'hostname' => getenv('REDIS_HOST'),
            'port' => getenv('REDIS_PORT'),
            'password' => getenv('REDIS_PASSWORD'),
        ],
        'session' => [
            'class' => yii\redis\Session::class,
            'as session' => craft\behaviors\SessionBehavior::class,
        ],
    ],
];

Note: if you're setting up both the cache and PHP sessions to use Redis you only need to include the redis component once.

If your Craft project uses a lot of plugins that make use of the cache, or if you're running multiple copies of your Craft application in a high availability setup this configuration should prove very beneficial. Even if neither of those things apply it still might help a little with overall performance.

Adding external services like Redis can have a great impact on your Craft app, but also comes with configuration and maintenance overheads that need to be considered.

Servd offers all of the above as standard on all subscription plans, and it's integrated into your Craft project with no changes needed from you!