If you're looking to improve the performance of your Laravel web application, then implementing a cache layer could be a good option. As a very high-level overview, using a cache allows data to be stored and then quickly retrieved. Common use cases include replacing slow or repetitive database queries, or even entire HTTP responses.

Although Laravel comes with a great, easy to use solution for server-side caching, there is still a lot to consider when implementing a cache layer in your application. What should be cached? How long should it be cached for? Where should we cache it?

The answer to all of those questions is usually "it depends on your circumstances", however we're going to tackle the last one. The Laravel cache service offers multiple cache "drivers", allowing different back-end storage engines to be used. When choosing which one is best to use, it is again likely to depend on your circumstances.

Do you need a cache that is quick and easy to setup / maintain? Where should the cache store be hosted? Should it be available to multiple servers? Is performance the ultimate priority? Performance is what I'll be focusing on.

Cache drivers: APC vs Database vs File vs Memcached vs Redis

The cache drivers we will be focusing on are those that come with the default Laravel installation:

  • APC (APCu)
  • Database (this cache driver uses Laravel's database engine, which is again driver based - we'll be using two - MySQL & SQLite)
  • File
  • Memcached
  • Redis

Laravel also comes with two other drivers that I won't be testing:

  • Array (data is stored in memory for the current PHP process (e.g. a HTTP request, running an Artisan command) so wouldn't be suitable for most people, it's mainly used for tests).
  • DynamoDB (an AWS proprietary NoSQL key-value based database, which you're only likely to use if you host all of your infrastructure on AWS)

Testing Laravel cache drivers

I'll be testing the read and write speed of each cache driver with 5 different types of commonly cached data:

  • Integer - a single number
  • Stats - a JSON encoded string of 100 numbers
  • Paragraph - a text string of 150 words
  • Article - a text string of 2500 words
  • Webpage - an entire HTML webpage (I've used the webpage for the most popular BBC news article at the time of writing)

I've written an Artisan command (available on GitHub) in a default Laravel 6 installation to make 1,000 reads and 1,000 writes for each of the above data types. For each test, the time taken to complete the action will be recorded in microseconds. This will then be used to calculate an average time for both reading and writing for each data type, for each cache driver.

As for server environment, I'll be testing on the lowest spec VPS available from Linode (1GB RAM / 1 CPU) that has been freshly provisioned by Laravel Forge, using the default configuration that it provides for PHP 7.3. There will be minimal load on the server as there will be no inbound HTTP traffic and only the default services running.

Laravel cache driver speed tests

APC cache driver

Test Read Write
Integer 0.770 2.416
Stats 0.679 2.367
Paragraph 0.631 2.128
Article 0.676 2.433
Webpage 0.694 2.120

Database (MySQL) cache driver

Test Read Write
Integer 642.146 390.471
Stats 714.820 412.997
Paragraph 811.301 383.895
Article 1151.277 412.056
Webpage 3643.461 765.362

Database (SQLite) cache driver

Test Read Write
Integer 1432.321 137.590
Stats 1353.896 137.828
Paragraph 1132.085 161.893
Article 1194.738 173.334
Webpage 2159.022 253.023

File cache driver

Test Read Write
Integer 147.066 33.503
Stats 132.957 35.460
Paragraph 153.218 35.498
Article 158.506 46.110
Webpage 395.767 165.265

Memcached cache driver

Test Read Write
Integer 63.500 35.403
Stats 63.671 38.796
Paragraph 63.031 37.054
Article 138.603 74.496
Webpage 1125.189 842.751

Redis cache driver

Test Read Write
Integer 57.925 54.762
Stats 55.013 54.390
Paragraph 60.338 56.676
Article 44035.899 78.775
Webpage 1192.044 378.57

Performance observations

From looking at the above results, it's clear that the APC drivers is by far the fastest Laravel cache driver in our tests with speeds far better than any of the others. There was little difference in the timings between the smaller and larger datasets.

Next up, the two memory based cache stores Memcached and Redis both produced similar results - although the write speeds were slightly better in Memcached and the read speeds were slightly better in Redis. You may have noticed the rather high read speed for the "article" data in Redis. Having tried slightly different amounts of data and different servers in different data centres, this anomaly still occurred.

The Laravel file cache driver came out in third place, with speeds roughly double those achieved with Redis and Memcached.

The second slowest Laravel cache driver appears to be the database driver connected to a MySQL (5.7) database, with the speeds being roughly 5 times slower than those achieved with Redis and Memcached.

Finally, the slowest cache driver in our tests was the  the database driver connected to SQLite (a flat file based database) - the speeds appear to be approximately 10 times slower than those achieved with Redis and Memcached.

So, which Laravel cache driver should I use?

As I mentioned in the start of this article, the answer is probably "it depends".

APC obviously gave the best results by far, however it can only be used by a single PHP process. So if you need you cached data to be accessed via HTTP requests and CLI, or even across multiple servers, you won't be able to use it. For simple, single server Laravel applications, it is probably your best choice.

If you don't mind a little extra server maintenance (having to install & maintain additional services), the memory based cache drivers Memcached and Redis are great options. A server provisioning tool like Laravel Forge with make the initial setup easier, and a fully managed hosted service will greatly reduce the amount of additional maintenance. If you'll be caching large amounts of data, many server providers offer high memory instances.

Whilst the the file based driver is incredibly easy to setup and offers OK speeds, you may run into problems with disk IO if your application will have high activity levels. It might be a good choice to start with, but you'll likely need to replace it with a different cache store if your application sees an increase in traffic.

Finally, we come to the database cache drivers. Again, they are a good option if you want a quick and easy solution as you're likely already running a database. If top-level performance is the priority, these won't be the answer for you as they tend to be the slowest, and will require other server resources - such as CPU usage for MySQL.


In conclusion

There is so much to consider when implementing a cache layer, and whilst better performance is likely to be your priority, you'll need to do further research, or even better, your own testing to get the best results.

You can find my test script here: https://github.com/gbuckingham89/laravel-cache-performance

If you want to discuss Laravel caching in more detail, feel free to get in contact.