How Caching Works in WordPress

Caching is sometimes served as a “holy grail” for all performance problems. It is not surprising that users often puzzle the statement “enough to use caching” in my presentations, seminars and workshops. Some in the WordPress community have come to refer to me as “the guy who hates caching.” It’s time to clarify what I really think about this issue. When and in what situations is caching really worthwhile? How to abandon it? What alternative solutions exist?

When should I use page caching?

Let’s start with the largest – page caching. Here’s how it works in practice:

  1. Visitor A goes to This page is not in the cache, so it runs PHP and the page is generated from the database. Before the page is transferred to the visitor, it will also be stored in the cache for a period of 10 minutes.
  2. Visitor B goes to 2 minutes after visitor A and therefore receives the same page, but this time directly from the cache. The pages transmitted by A and B are completely identical.
  3. Visitor C visits 15 minutes after visitor A, and since the cached version of the page has expired, the query results in PHP executing, and the page is regenerated, just like with visitor A.

If every visitor who scans the page within the set time period fits within the cache lifetime, the page is issued very quickly. Caching can improve performance and, more importantly, scalability. This may look attractive, but page caching also has its serious drawbacks.

  1. If you want to deliver dynamic content, personalized, different for each user – this is implemented using javascript (ajax), which is launched after the HTML document is delivered to the visitor. This is cool, but this requires an additional request to the server. If you use caching, you will encounter a problem related to your dynamic Ajax queries.
  2. If something works fast for you, it does not mean that the same will work quickly for others. Web sites do not have a single entry point, and visitors go to your site in different ways. This is especially true for WooCommerce when visitors use Google and go to product pages. Someone goes through Google Shopping, Yandex Market, etc. To cope with this problem, some webmasters try to form a basic page cache for robots that bypass the site to make sure that all pages have been pre-cached. But in practice this does not always work. Such a cache is vulnerable, it’s difficult to configure and configure, it’s hard to maintain, it all takes a very long time – and it’s not necessary in general.
  3. You lose control over the real performance of your site, do not know how the code works (or it does not work as it should). If you use page caching, you lose understanding of how fast your site is, how good your code is. Experience shows that insufficient concern about site performance leads to the fact that sites fall during Black Friday or in the process of conducting large advertising campaigns.

What about caching plug-ins, such as W3 Total Cache?

WordPress plugins, such as W3 Total Cache, work by analogy with any other page caching. They store the version of the pre-generated page in a file system or memory and issue it to users until it expires. W3 Total Cache is used on 1 million sites, but that does not mean that it’s a good idea. Especially if you use fast hosting.

W3 Total Cache is a very large plug-in, and for most sites it adds a lot of extra code. More code – more problems. If you really need page caching, you do not need to run it at the PHP level of your application, because PHP itself is slow enough. Caching pages should be performed as close as possible to users on the server (nginx in our case).

W3 Total Cache shows how you can load pages in less than 2 seconds using the twentysixteen theme. A similar test on our servers led to the fact that the pages were delivered in less than 100 ms without using caching.

In what situations do you need page caching and why?

Caching pages was invented to scale sites with huge traffic to make it easier to handle traffic spikes. It was invented at the time when users turned to web resources mainly for reading news articles. Pages of news sites are mostly static and are updated only occasionally. In this case, page caching is appropriate, but modern sites are more reminiscent of applications.

Modern sites are more complex, dynamic and more personalized. Their code is pretty confusing, and adding even more complex mechanisms (read: caching methods) on top of this complex code is not the best idea. In practice, you add one more level of technology that introduces new single points of failure that require special maintenance, upgrades, and operations. As a result, bugs are more difficult to detect and solve, and overall development becomes much more expensive. If you are generating performance around page caching, then I guarantee that everything will stop working if there are any interruptions with caching.

Therefore, the answer to the question is to write good code and queries, and take into account that the solution must be scalable. You can use page caching to handle sudden bursts of traffic, as news resources did (and now do).

At normal times with normal traffic, you should be able to disable page caching without worrying about it. If you did everything correctly, then you can disable caching on those days when traffic is high enough – and your site will not crash.

Most of our shops work without caching pages – even on those days when traffic is very high, as, for example, on Black Friday.

Object caching WordPress – you use it, but do not know about it

Many people do not know that WordPress object caching is used on virtually all WordPress sites. Yes, the object cache is effective even if you do not use a third-party object cache, like MemCached or REDIS.

How does the object cache work in WordPress?

  1. You make a query, for example, for the values of postmeta by using get_post_meta ().
  2. WordPress executes the query and retrieves the results from the database, and automatically saves the result to the object cache (memory).
  3. You get the result and use it somewhere in your code.
  4. Later in your code, you make another request to get_post_meta for the same data.
  5. WordPress already has this data in the object cache, and therefore returns the result directly from the cache without a re-query to the database.
  6. The page is delivered to the visitor, and the object cache is cleaned (memory is freed).

Not all functions in WordPress store their results in the object cache, but get_post_meta does this. This is due to the fact that _postmeta table in the database can grow very quickly, and queries can become quite resource intensive.

You can add results to the object cache yourself to speed up the reuse of the same data in the future. If you write your own queries using, say, WP_Query, you can save the results to the object cache. It is important to remember that, as with any other caching, you should not rely solely on it. Make sure that your code does not come from the assumption that the results are stored in the object cache.

You can check the performance of the object cache and the number of queries to the database by installing a plugin like Query Monitor. In my tests with standard WooCommerce, the normal percentage of hits in the object cache was 95-98%.

How to use the WordPress object cache for your own queries

What does this code do? Here we try to get $result first, and then we check if there is anything in this variable. wp_cache_get() returns false if the variable does not exist. If there is no data, we run a query for our data, and then save the result with wp_cache_set() so that the data is available for our next request.

What about third-party object caches, such as MemCached and REDIS?

An external object cache allows you to implement what is often referred to as a “permanent object cache”. This is a cache of objects that is not cleared during pageviews, so it saves the data while viewing different pages. Smart idea, is not it? But, as always with caching, not everything is so simple.

  1. The potential increase in performance from using a persistent cache is associated with transitions that bypass the object cache. Given that the percentage of getting into the standard object cache is somewhere around 95-98%, the potential performance gain can be 2-5% of the query. In addition, the external object cache adds an additional delay, since this is a third-party application – so it will slow down those 95-98% that were passed directly to PHP earlier. The added delay + performance increase from the external object cache often goes to the minus for online stores.
  2. Even if you use an external object cache, you can not verify that the information exists in it when you write the code.
  3. If you depend on an external object cache to speed up page loading, this means that your code is bad, your database queries are weighty or too many. The real problem is your code, not how quickly the database responds to queries. For this reason, you should not rely on crutches in the form of MemCached or Redis.
  4. If you use a fast database that is optimized and use indexes correctly, you do not need an external object cache.

If you do not need an external object cache, then its use can only do much harm

This applies to all technologies that you include on your stack, but which you do not need. In the end, you can depend on them, although you do not even need them. If you depend on such technologies, then you increase the likelihood that something can go wrong. In addition, each new technology on the stack requires installation, configuration, maintenance, security updates – and introduces one more point of failure.

Transients is a good alternative, but they too can break the site

Transients (temporary data) are used by the WordPress system itself, and by different plug-ins. Their concept is quite simple. You make a request and save the result or part of it in the database for later use. Unlike the object cache, you do not need additional technologies to make this data permanent in the process of browsing the pages, because they are stored in the database. Transients may have expiration time, or may not have – it’s your choice.

I personally do not support the fanatical use of transients, and that’s why:

  1. Transients are stored in the _options table of WordPress. This table is already quite actively used, and excessive inflating it can cause problems with blocking (the queue of requests).
  2. Excessive use of transients causes the _options table to grow. Each individual pageview depends on this table, and a large table of options may reduce site performance.
  3. Transients that have not expired are requested during each page load via wp_load_alloptions (). This reduces the performance of all page views.

In this case, transients can give pluses in terms of performance, if they are correctly used. If you request data that is used and changed rarely, you can save the result to transients. For WordPress it is much easier to get the value from the X key of the options table than to sample all the other tables. If you are using transients, make sure that the _options table does not grow too much, clean transients that are no longer used or have expired. Never use transients for data that requires frequent updates, this will negatively impact performance.

Caching fragments is a good option if used correctly

A fragment cache is a type of caching when you save an item, part of a page, or something else, which is resource intensive for generation and / and is often used.

Caching fragments means saving the result (HTML output) so that it can be delivered much faster. The idea is simple and gorgeous. You can choose which elements to cache, and you do not need to cache full output, as with caching pages.

In WordPress, the process of caching fragments is equivalent to object caching, since there are no restrictions on what data you can cache. The same principles are applied – do not start from the assumption that something was cached, write a full code with checks.

Many implement caching of fragments in memory. But this requires an external object cache, so that elements are available while browsing the pages. I recommend carefully using fragment caching – I advise you to store data in transients instead of object cache. As a result, you will get the same results in terms of performance without adding additional technologies to your stack.

How to save transients

Here we get $ output from transient and check if $ output exists. If get_transient () prints false, then we generate the data and store it in transient for later use.

What kind of caching method should I use?

Use page caching to scale the site. It was created for this, not to improve performance. Do not depend on him. You should be able to disable caching without significant performance degradation.

Use the object cache where possible, especially for WooCommerce, but avoid external caches because they can lead to new problems. Instead, it’s best to switch to fast hosting with high-performance databases.

You must use transients for frequent queries that change little. Be sure to set a suitable expiration date based on how often the data should be updated. Also, make sure that the expired transients are deleted. Use fragment caching in transients for items that consume a lot of resources and are used quite often.

Authored By Imran Yousaf

I am Imran Yousaf, a computer geek, founder of the site I am a die hard fond of open-source software and Linux operating system. In addition to Linux, I am interested in everything related to information technology and modern science.

Leave a Reply

Your email address will not be published. Required fields are marked *