The Developer's Guide To Optimizing A WordPress Site

Website performance matters not only in providing a good user experience but also in the world of SEO. Every aspect of an SEO campaign should be considered, and site performance is an integral part of success.

WordPress has a number of pieces that must all work together in order to provide a great user experience, and optimizing those pieces will ensure that your site’s performance is where it needs to be to provide a pleasant experience to your visitors.

Let’s take a look at the pieces and see how optimizing them can increase the performance of your WordPress site.

Disk

Quite a bit can be said about the impact of disk performance on applications. So much so, that there are many false notions about the value of memory-based caching as a silver bullet solution. Assuming your hardware is modern, here are some rules of thumb for thinking about your architecture:

A non-shared local disk will always give the most consistent and reliable performance.

Network (shared) storage definitely plays its role, but will not scale as far as or in the way that you would like. Always break up the problem you need to solve into pieces optimized for the need.

Never compromise on data redundancy even when using cloud-based solutions.

MySQL

The query cache is your best friend. MySQL has been proven to be a scalable relational data store, and there’s no reason why it cannot continue to work for WordPress for years to come.

You’ll want to ensure that the query cache is enabled and performing well for your site. That will make sure that MySQL is doing as little work as possible, freeing up resources (hopefully) for more important things than redundant queries.

You’ll also want to make sure that you use a tool like mysqltuner or similar to ensure that your table performance (buffers, etc.) is optimal. Switching engines to InnoDB, which now has support for full text search, is recommended for higher traffic sites. You won’t compromise the native WordPress search quality by making the switch. I recommend the Percona distribution of MySQL, especially if functionality like sharding, read replicas, etc, allow it to scale as your needs grow.

Once you’ve ensured that MySQL your data store isn’t a bottleneck, you need to analyze your queries generated by your theme and plugins to either optimize them (reduce their response times), reduce their number through refactoring code or various caching techniques. Remember that by default, using transients in WordPress ‘moves the problem’ of caching something like a time consuming API request (API requests become expensive because they block execution while waiting on and processing responses from third parties) and puts it into the database (wp_options table). That may not be such a bad thing if that data was not serialized and stored in the same table as various other settings in WordPress.

Fortunately, there are new options for reducing database load that will be highlighted shortly. New Relic makes it trivial to disseminate the goings on in your environment.

PHP

PHP is slow. That’s not the fault of WordPress, nor is it anyone else’s fault; technology simply keeps moving forward. What do we do about it? Use New Relic’s stack traces to get an empirical view on where optimizations can be made. Some rules of thumb to consider:

The larger the memory usage, the greater the execution time.

Take advantage of PHP 5’s auto load to reduce memory usage.

Use memorization and avoid loops wherever possible to reduce execution time and memory usage. Avoid opening more files than necessary to reduce calls to disk and memory usage. Use include and require rather than include_once and require_once.

Opcode Cache

APC is a ‘free, open, and robust framework for caching and optimizing PHP intermediate code.’ That means that when added to your web server you can realize dramatic speed improvements (especially with well written code). APC keeps the interpreted (executable) version of your code in memory so that requests for it do not have to be re-interpreted. APC also offers an object store, allowing objects you create to be stored in memory right next door to the scripts that need them. The only drawback to this level of caching is that it’s local to each respective application server you have. That means the cache for objects is rebuilt on each server (wasted CPU time) and, more importantly, purging of objects is tricky.

There are multiple copies of objects everywhere, potentially with various ‘states’, but there are solutions to the purging issue.

After optimizing your database and architecture it is time to fine tune your WordPress install.

Here are some tasks you can complete to ensure you are running at peak performance:

Plugins

This may be obvious to some but it is something that often gets overlooked. Make sure your WordPress plugins are up to date. Developers are always looking for ways to improve their plugins, and one of these ways is to increase performance of their code with each release. This is a very simple way to ensure that your plugins are always running at their peak performance. Unused plugins should be disabled so they are not using valuable resources and loading unnecessary code. Not only will this save space on your servers, it will also ensure that vulnerabilities are protected from developers that are slow to release patches or no longer support their plugin code.

Use WordPress Caching

The best known WordPress caching tool is W3 Total Cache, but there are others that are also recommended by the WordPress community, like BatCache and WPSuperCache. These caching plug-ins speed up your site and lead to a large number of benefits for visitors and users who re-visit your site.

Browser Caching

Browser caching can help to reduce server load by limiting the number of requests per page. For example, by setting the correct file headers on files that don't change (static files like images, CSS, JavaScript, etc.) browsers will then cache these files on the user's computer. This technique allows the browser to check to see if files have changed, instead of simply requesting them. The result is your web server can answer many more 304 responses, confirming that a file is unchanged, instead of 200 responses, which require the file to be sent.

Look into HTTP Cache-Control (specifically max-age) and Expires headers, as well as Entity Tags for more information.

CDN (Content Delivery Network)

Using a CDN allows you to store images and large files on third-party clustered servers around the world whose sole task is to bring content geographically closer to your website visitors, thus speeding up page download times.

Avoid Using the Google SiteMap Generator Plug-in

This probably came as an unexpected suggestion, didn’t it? This well-known Google Sitemap plug-in rebuilds itself from scratch each time your sitemap changes, rather than incrementally adding new changes as they occur. Instead, select another leading plug-in from the WordPress repository that overcomes this limitation. By the way, you should only download plugins from WordPress repository and not third party sites which may be phishing attempts, or may include malware in the download.

Minify

Its value may be reduced to some degree when HTTP 2.0 arrives, but until then, especially for mobile, minification is vital to improving end user experience. Reducing the file size and number of files (and therefore HTTP transactions) has a dramatic impact on the user’s experience with your site.

Unfortunately, not all Cascading Style Sheets (CSS) or JavaScript (JS) lends itself to the various techniques in popular minify libraries. Developers should take steps using jQuery or WordPress Core to provide a fully optimized version of their files to take the load off the publishers.

There are various tools for WordPress that support the minification process. When making a selection, ensure you pick one that caches the minified files to disk, respects the differences between templates, supports local and remote files and most importantly is compatible with content delivery networks and mobile plugins.

Widgets

Be suspicious of all widgets (or sidebar content) that will force the user to poll other DNS servers. Delicious for example will link to various sites, which might delay the loading until information is passed to the user.

Also, check if your theme is using custom widgets do draw recent comments of posts. If this is not handled correctly, it will poll the database every time, considerably increasing your load.

If you're using a lot of widgets, a good idea would be to use the WP Widget Cache plugin (in addition to standard caching) to reduce the processing time for their output.

By applying as many of these changes and fine tuning things as much as possible you can greatly increase your WordPress load times, and your visitors will have a better experience on the website.