October 31, 2022

How does caching work in WordPress?

Explanation of the various caching techniques in WordPress and how to do without them with proper application code.

Caching can give the impression that it is the "Holy Grail" for all performance problems. Unsurprisingly, people raise an eyebrow when I say "Stop using caching"In my presentations or consultations.

However, as we have always explained everywhere, much of our success as a Web Performance Oriented Hosting company is due to Cache mechanisms and technologies, ranging from PHP cache like Zend Opcache to Enterprise-grade Full Page Cache like Varnish Cache.

It is not difficult, therefore, to risk in some contexts being accused of hypocrisy with complaints such as: "Why, didn't you say that caching improves performance and solves problems?"

So, it's time to clarify what I really mean by this topic, when and what it should be used for. And perhaps most importantly, when not use caching and look for workarounds directly on the development side.

We, as a Hosting and systems engineering company, solve problems on the systems side without going into the development side (if not for single queries, or very small bugs) on customer sites that complain of performance and speed problems, so it is normal that caching techniques can hide the problems on the application side, exactly how the dust hides under the carpet.

The problem remains, but in fact it does not create tangible problems and the customer and their visitors are happy to view sites or make purchases on sites that do not go offline. However, we have always liked an adequate and performance-oriented approach from the developers.

When should you use full page caching?

Let's start with the greatest of all. Full Page Cache or simply page caching is a technique in which you temporarily store a pre-generated version of a page to deliver the exact same code (HTML) to visitors within a limited amount of time.. Here's how full page cache works:

  1. Visitor A visits abc.com/page. This page is not cached, reaches PHP and is generated from the database. Before being served to Visitor A, it is also cached full page with a 10 minute expiration.
  2. Visitor B visits abc.com/page 2 minutes after visitor A and is then served with the same page, but this time directly from the cache. The pages served to Visitor A and B are identical.
  3. Visitor C visits abc.com/page 15 minutes after visitor A and because the cached version of the page has expired, the request reaches PHP again and the page is regenerated just like visitor A.

Since everyone who visits this page in the time frame that a valid cached page exists, the page can be delivered very quickly.

Almost no resources are used to provide a cached page, and thus caching the entire page can improve performance and, more importantly, scalability. It may sound very interesting, but full-page caching also has some big drawbacks.

  1. If you wish to deliver dynamic, personalized or otherwise different content to different users, this must be addressed with javascript (ajax) which is executed after the HTML document has been delivered to the visitor. This can work fine, but it requires another additional request to the server. If you use caching to avoid writing fast code, you will continue to experience performance issues with your dynamic ajax requests.
  2. Just because something works fast for you doesn't mean it's fast for everyone. Websites don't have a single point of entry, and visitors come to your site through a variety of pages. This is especially true of WooCommerce, where visitors use Google and go through product pages. Or, if you Google Shopping on the full catalog with links directly to the product pages. To solve this problem, some people even try to solve it by "luring" the full page cache by using spiders to index the whole site in order to make sure each page is cached in advance. In practice, this doesn't work well. It is vulnerable, difficult to set up and configure properly, difficult to maintain and time consuming, and completely unnecessary.
  3. You lose control of your website's actual performance and how the code works (or doesn't work as it should). If you use full-page caching, you lose the sense of what your site's real response time is and how good your code is. Experience shows that a lack of focus on real-world performance is the main reason sites crash on days like Black Friday or when deploying large campaigns.

What about caching plugins like W3 Total Cache?

WordPress plugins like W3 Total Cache work like all other cache pages. They store a pre-generated version of a page in the file system or memory and offer it to users until expiration. W3 Total Cache is used by 1 million websites, but that doesn't mean it's a good idea. Especially if you use fast hosting.

W3 Total Cache is a very large plugin, and for most sites, it just adds a lot of unnecessary code to the website. The more code, the more things can go wrong. If you were to really do full page caching, this shouldn't be done in the PHP part of your application because PHP is slow. Full page caching should be done as close to the user as possible on the web server (NGINX in our case).

W3 Total Cache is about loading pages in under 2 seconds by showing a theme like TwentySixteen. To clarify, a similar test on our servers will be delivered in about 150 milliseconds without the use of caching, not seconds.

So when should you use full page caching and why?

Entire page caching was created to resize websites with very traffic to more easily manage traffic peaks. Full page caching was invented when people used the web primarily to read news articles. Generating unique content for each visitor is not sensible for newspapers, because their pages are mostly static with rare updates. For this scenario, full page caching is absolutely right, but only for sites that don't require logged in users or custom content, in fact today's websites are more like applications.

Contemporary websites are more complex, dynamic and increasingly personalized. Code is getting more and more complex, and adding even more complex mechanisms (read caching techniques) over already complex code isn't always a good idea. In practice, another level of technology will be added that introduces new single points of failure, requires dedicated maintenance, updates and operations. It will make bugs harder to fix and general development harder (more expensive). If you base your performance on full page caching, I can close to ensure the solution will collapse if caching stops working.

The answer to the question is therefore to write good quality code and queries and keep in mind that the solution must be scalable. It's okay to use full page caching to handle sudden traffic spikes, just like newspapers did and still do.

You should be able to turn off full page caching on a normal day, with normal traffic, without getting nervous. And if you do it right, you should be able to turn off full page caching even on busy days, without crashing your website.

On Managed Server, most stores operate without full page caching, even on high traffic days like Black Friday.

WordPress Object Cache: You use it without knowing it

Many people are unaware that the WordPress object cache is in use on almost all WordPress sites. And yes, Object Cache is effective even if you don't use an external Object Cache, like MemCached or REDIS.

How does the WordPress object cache work?

  1. You make a request for using postmeta values ​​ie get_post_meta()
  2. WordPress executes the request and gets the result from the database and automatically stores the result in the object cache (memory, RAM)
  3. You get the result and use it somewhere in your code
  4. Later in your code, do another one  get_post_meta() request for the same data
  5. WordPress already has it in the object cache and returns it directly without querying the database again
  6. The page is delivered to the visitor and the object cache is emptied (memory freed)

Not all WordPress functions save their results in the object cache, but  get_post_meta() they do it. This is because the _postmeta table in the database can get very large and the requests can get expensive (use a lot of processing resources).

As a developer, you can add results to the Object Cache yourself , so that reusing the same data later can be faster. If you write your queries with for example WP_Query, you will need to store the results in the object cache yourself. It's important to remember, however, that, as with all caching, you can't trust it. So make sure you don't write code that assumes your results are in the object cache.

You can check the performance of the object cache and the number of database queries by installing a plug-ins such as Query Monitor.

In our tests with a normal WooCommerce, a normal Object Cache success rate is between 95% and 98%.

How to use the WordPress object cache for your queries

$ result = wp_cache_get ('some_unique_name'); if (false === $ result) {$ result = $ wpdb-> get_results ($ query); wp_cache_set ('some_unique_name', $ result); } // Do something with $ result;

What this code example does is first try to get a  $result, then check if there really is a $ result. wp_cache_get()returns falseif it doesn't exist. If there is no data, we query for our data and then store it with in wp_cache_set() so that they are available for future requests.

What about external object caches like MemCached and REDIS?

An external object cache can provide what is more specifically called a “persistent object cache”. This is an object cache that is not downloaded between page views; therefore, it stores its data in different page views. Smart idea, right? But as usual with caching, it's not that simple.

  1. The potential performance gain from using a persistent Object Cache is limited to hits that fail Object Cache. Using the default non-persistent cache access rate of 95% -98%, the potential for performance improvement is between 2% and 5% of the request. Also, an external object cache will add additional latency because it's an external application, so it will slow down 95-98% that was served directly in PHP before. Net gain from added latency + performance gain from external object cache often goes bad for ecommerce stores.
  2. Even if you use an external Object Cache, you cannot trust the existence of the information when writing the code.
  3. If you depend on an external Object Cache to load pages at a decent speed, it means your code is invalid, the database queries are too heavy, or there are too many of them. The real problem is in your code, not database responsiveness. That's why you shouldn't use the MemCached or Redis patch.
  4. If you are using a fast, optimized database that uses indexes correctly, you do not need an external Object Cache.

If you don't need an external Object Cache, it can be harmful to use one

This really goes for all the technology you include in your web stack, which you don't need. If you have it, the chance of getting addicted to it is great, even if you don't really need it. If you depend on it, you increase the chances of something going wrong. Additionally, each technology added to the stack requires installation, configuration, maintenance, security updates, and introduces another single point of failure.

Transients can be good, but they can also hurt your site

Transients are used by WordPress and a variety of plugins, and the concept is quite simple. You make a request and save the result, or parts of it, in the database for later reuse. Unlike Object Cache, no additional technology is needed to make this persistent across page views, because the data is stored in the database. Transients may or may not have an expiration time - it's your choice.

I personally don't like the excessive use of transients, and there are many reasons for that

  1. Transients are saved in the WordPress _options table. This table is already heavily used, and excessive writing to _options can introduce blocking (queuing) problems.
  2. Excessive use of transients will result in a large _options table. Each individual page view depends on this table, and a large option table can degrade performance on all page views.
  3. Transients that do not expire will be queried on every page load (autoload) via wp_load_alloptions (). This will reduce performance on all page views.

But that said, transients can be great for performance when used correctly. If you are querying for data that is used often and rarely changed, it may be a good idea to store the result in transient. It is much easier for WordPress to retrieve the value from the X key in the options table, rather than making selections on other tables. But, if you use transients, be sure to keep an eye on the _options table to make sure it doesn't grow wild, and be sure to implement cleanup for transients you no longer use or have expired. And never use transients for data that requires frequent updates, as it degrades performance.

Fragment caching is good when used correctly

Fragment Cache is a type of caching where you store an element, part of a page, or something else whose generation is costly in terms of resources and / or is used often. Many have chosen to implement Mark Jaquith's feature to perform Fragment Caching in WordPress.

Fragment Caching means storing a result (HTML output) so that it can be delivered much faster later on. The idea is as simple as it is surprising. You can choose which items to cache, and you don't need to cache the entire output, such as full page caching.

The way you do this in WordPress is equivalent to Object Caching, because there is no limit to the data you can cache. Therefore, the same principles apply; never trust something is cached, make sure you don't depend on it and focus on your code rather than taking the fragments cache shortcut.

Many implement memory-based fragment caching. But for this to take effect, an external Object Cache is required to make items available in page views (see above). I recommend a gentle use of fragment caching and data storage in transients. In practice, this will give you the same results in terms of performance, without adding additional technology to your stack.

Here's how to save transients

$ output = get_transient ('some_unique_key'); if ($ output === false) {$ output = 'Some data'; set_transient ('some_unique_key', $ output, 3600); } // Do something with $ output

In this code example we read $output from a transient and test if $ output exists. Self  get_transient()returns false , we generate the data and store it in a transient for later use.

Which caching technique should I use and when?

It uses Full Page Cache storage for scaling, that's what it's done for: it's not done for performance boost. Make sure you don't get addicted to this. You should be able to disable whole page caching without experiencing any significant performance hit.

Use Object Cache as much as possible, especially if you use WooCommerce, but avoid external Object Caches, they will introduce all kinds of new problems. External caches will shift your attention to the wrong parts of your application. A better trick is to get a faster hosting, with high performance databases as ours.

You should use transients for frequent queries that don't change much. Make sure you set an appropriate expiration date based on how often the data needs to be updated.

Also make sure to delete the expired transients. Use the fragments cache in transients for items that are resource intensive and used frequently.

Do you have doubts? Don't know where to start? Contact us!

We have all the answers to your questions to help you make the right choice.

Chat with us

Chat directly with our presales support.

0256569681

Contact us by phone during office hours 9:30 - 19:30

Contact us online

Open a request directly in the contact area.

INFORMATION

Managed Server Srl is a leading Italian player in providing advanced GNU/Linux system solutions oriented towards high performance. With a low-cost and predictable subscription model, we ensure that our customers have access to advanced technologies in hosting, dedicated servers and cloud services. In addition to this, we offer systems consultancy on Linux systems and specialized maintenance in DBMS, IT Security, Cloud and much more. We stand out for our expertise in hosting leading Open Source CMS such as WordPress, WooCommerce, Drupal, Prestashop, Joomla, OpenCart and Magento, supported by a high-level support and consultancy service suitable for Public Administration, SMEs and any size.

Red Hat, Inc. owns the rights to Red Hat®, RHEL®, RedHat Linux®, and CentOS®; AlmaLinux™ is a trademark of AlmaLinux OS Foundation; Rocky Linux® is a registered trademark of the Rocky Linux Foundation; SUSE® is a registered trademark of SUSE LLC; Canonical Ltd. owns the rights to Ubuntu®; Software in the Public Interest, Inc. holds the rights to Debian®; Linus Torvalds owns the rights to Linux®; FreeBSD® is a registered trademark of The FreeBSD Foundation; NetBSD® is a registered trademark of The NetBSD Foundation; OpenBSD® is a registered trademark of Theo de Raadt. Oracle Corporation owns the rights to Oracle®, MySQL®, and MyRocks®; Percona® is a registered trademark of Percona LLC; MariaDB® is a registered trademark of MariaDB Corporation Ab; REDIS® is a registered trademark of Redis Labs Ltd. F5 Networks, Inc. owns the rights to NGINX® and NGINX Plus®; Varnish® is a registered trademark of Varnish Software AB. Adobe Inc. holds the rights to Magento®; PrestaShop® is a registered trademark of PrestaShop SA; OpenCart® is a registered trademark of OpenCart Limited. Automattic Inc. owns the rights to WordPress®, WooCommerce®, and JetPack®; Open Source Matters, Inc. owns the rights to Joomla®; Dries Buytaert holds the rights to Drupal®. Amazon Web Services, Inc. holds the rights to AWS®; Google LLC holds the rights to Google Cloud™ and Chrome™; Facebook, Inc. owns the rights to Facebook®; Microsoft Corporation holds the rights to Microsoft®, Azure®, and Internet Explorer®; Mozilla Foundation owns the rights to Firefox®. Apache® is a registered trademark of The Apache Software Foundation; PHP® is a registered trademark of the PHP Group. CloudFlare® is a registered trademark of Cloudflare, Inc.; NETSCOUT® is a registered trademark of NETSCOUT Systems Inc.; ElasticSearch®, LogStash®, and Kibana® are registered trademarks of Elastic NV This site is not affiliated, sponsored, or otherwise associated with any of the entities mentioned above and does not represent any of these entities in any way. All rights to the brands and product names mentioned are the property of their respective copyright holders. Any other trademarks mentioned belong to their registrants. MANAGED SERVER® is a registered trademark at European level by MANAGED SERVER SRL Via Enzo Ferrari, 9 62012 Civitanova Marche (MC) Italy.

JUST A MOMENT !

Would you like to see how your WooCommerce runs on our systems without having to migrate anything? 

Enter the address of your WooCommerce site and you will get a navigable demonstration, without having to do absolutely anything and completely free.

No thanks, my customers prefer the slow site.
Back to top