Optimized WordPress hosting is a subject on which a lot is written about. And therefore, this post is not about where to host your WordPress blog, or who offers the best WordPress hosting. This post is for you developers, what you can do to optimize your WordPress hosting stack.
Or for any other PHP web application for that matter.
This post is not about setting up high-availability, fail-over, clustering, IIS versus Nginx versus Apache, RAID 1, 5, 6, 10, different types of storage, and so on. It’s about solving performance issues! This post tackles most of your performance issues, by explaining important configuration settings for PHP & MySQL, server, security, and so on.
Discover how this very blog has optimized its WordPress hosting environment
and how you can too…
When reading Facebook groups like Advanced WordPress (AWP) or WordPress Development Stack Exchange, you often find questions like:
Will it affect the performance of the site if we increase the number of records in
wp_poststable by 10000 records? At this moment there are 200 posts.
Of course it will affect performance, doh! :) But, you can do a lot to optimize & tune your server/VPS and WordPress hosting.
Server hardware & separate web and MySQL services
One of the most important tips I can give you: separate services.
Whether you run your WordPress blogs on a VPS or bare-metal server, make sure you separate different server types and services. A lot of problems arise from having both Apache/PHP and MySQL on the same server, because MySQL loves memory. Approximately 80% memory needs to be available to MySQL.
My advice for you is to separate them to two servers, dedicated and optimized for their purpose (web or MySQL). Sure it’ll cost you an additional $10/m for an extra DigitalOcean droplet, but trust me: it’s worth it.
Isn’t it true that, when you (start to) develop WordPress websites for clients, and you host them yourself, you find yourself in a situation where you need to know a lot about “stuff” other than WordPress development? These 10 practical tips helps you tackle the most common performance issues.
As always, to tune MySQL you need to run an as high version of MySQL as possible. That means running MySQL 5.7, MariaDB 10.1 or Percona Server 5.6, at the time of this writing. Some MySQL administration experience is recommended for optimizing these settings.
InnoDB storage engine
Make sure your MySQL database tables are of the InnoDB storage engine. Nowadays MyISAM is outdated, just like PHP 5.3/5.4, .NET 3.5 and Windows Server 2003 are. All MySQL optimizations are for the InnoDB storage engine, so switch to that.
Execute the result set of the following statement on your database to convert your old MyISAM tables to InnoDB:
SELECT CONCAT('ALTER TABLE ',table_schema,'.',table_name,' ENGINE=InnoDB;') FROM information_schema.tables WHERE engine='MyISAM' AND table_schema NOT IN ('information_schema','mysql','performance_schema');
The output procuded will be something like:
ALTER TABLE db-name.table1 ENGINE=InnoDB; ALTER TABLE db-name.table2 ENGINE=InnoDB; ALTER TABLE db-name.table3 ENGINE=InnoDB;
InnoDB Disk I/O performance:
As of MySQL 5.5, InnoDB disk i/o performance can be increased by increasing the
innodb_read_io_threads settings in your MySQL server’s
my.cnf file. These are very important settings.
Starting with MySQL 5.5.4, you can also divide the InnoDB buffer pool into multiple instances with multiple innodb_buffer_pool_instances.
However, one important detail to remember is:
This options takes effect only when you set theMySQL InnoDB performance improvement: InnoDB buffer pool instances
innodb_buffer_pool_sizeto a size of 1 gigabyte or more.
So when dividing your InnoDB buffer pool into 6 instances, you’ll need at least 6 GiB RAM…
MySQL query cache You want to have MySQL query cache enabled on your MySQL database server, and have it configured with a proper value.
MySQL Query Cache is deprecated as of MySQL 5.7.20, and is removed in MySQL 8.0.
RAM, SSD, and CPU
MySQL loves memory (RAM). Make sure your server has plenty of it, and some more. About 80% of the RAM needs to be available for MySQL, and when you start dividing Innodb_buffer_pool_instances, query-cache, and various buffer sizes, RAM consumption increases rapidly.
Because SSD offers the best read/write (disk I/O) performance, SSD’s are a must too. If you can, switch to NVME disks.
If you don’t need MySQL’s binlog -or binary log, then disable it. Having MySQL’s binary log enabled will increase read/write operations on your disk. Do enable the slow query log to identify slow running database queries. The following example enables the slow query log for queries running three (3) seconds or more:
slow_query_log = 1 long_query_time = 3.000000 slow_query_log_file = /var/log/mysql/slow.log
Through this MySQL slow log, I once found that the autoload column of the wp_options table wasn’t indexed. You can fix that easily too: wp_options table autoload index.
Don’t save on CPU power, because MySQL likes to use the CPU for heavy calculations as well.
Web server optimization – PHP
No Apache, Nginx or IIS optimizations here, as I feel the web server is not often the bottleneck when a WordPress site is slow – but maybe you have a great tip for this? Share a comment!.
As with MySQL versions, go with the highest possible version: 5.6.18, or preferably 7.0.3 -at the time of this writing, if all your code is PHP 7 compatible. Some PHP settings need optimization too, I discuss them below:
Zend OPcache PHP extension is in PHP nowadays, so why not enable OPcache and use it? I recommend you do. In your
php.ini verify the following line is not commented out:
zend_extension = php_opcache.dll
You have to properly configure and optimize OPcache to take fully advantage of this opcode cache.
For IIS, set up WinCache and be sure to disable WinCache opcode cache in favor of OPcache’s opcode cache:
extension=php_wincache.dll wincache.ocenabled = 0 wincache.ocachesize = 0
Note: The .dll-part comes from my Windows Server hosting environment. Because of slow development, I stopped using WinCache on our web servers. OPcache is good enough, even on Windows Server.
Be careful when enabling WinCache server-wide though, it might consume all available memory.
Set a good realpath_cache_size for PHP
realpath_cache_size sets the size of the realpath cache to be used by PHP (e.g, the file locations on disk). Increasing
realpath_cache_size can improve PHP performance a lot, and this value should be increased on systems where PHP opens many files.
The following section will give you some quick tips on how to improve the speed of your website.
Optimization is key.
- check out my WordPress and MySQL categories to learn more about various WordPress and MySQL optimization techniques.
- move the database from MySQL to Elasticsearch, especially with large WooCommerce ecommerce WordPress shops. Not only is Elasticsearch much faster than MySQL, it also provides and/or searches that are not possible using the normal WordPress MySQL search (like select all products with tag A and tag C, but not tag B or E).
- use Redis as a full page cache, or install Varnish Cache and deploy it in front of your web server. (Core Caching Concepts in WordPress is a great article introducing you into WordPress caching – Caching concepten in WordPress: wat is caching en hoe maakt dit WordPress sneller? is my Dutch translation on ITFAQ.nl).
- install a cache plugin like WP-Super-Cache or Cache Enabler (they’re the cache plugins I prefer, but there are many other cache plugins out there). With WP-Super-Cache and Cache Enabler you can speed up WordPress by serving gzip compressed files.
- Use SSL in WordPress, it’s the de-facto standard nowadays!
Enable GZIP compression in WordPress .htaccess
The easiest way to enable gzip compression in WordPress, for your images, CSS and JS files, is to add these lines to your .htaccess file in the root WordPress folder:
If your server supports it, enable BROTLI compression instead of gzip. Set an Brotli output filter in
Caveat: be aware that not all plugins and external optimization sites / services recognize Brotli compression yet. You may get notices about not having gzip enabled…
Leverage browser caching
Add the following lines to your WordPress .htaccess to enable browser caching for resources:
Enable HTTP Connection keep-alive:
Set the following header directive in your .htaccess file to enable HTTP Connection keep-alive:
Header set Connection keep-alive
Remember that for everything you add to your .htaccess file to optimize WordPress, you don’t have to install a plugin! This saves on PHP files and CPU processing time. Win win!
WordPress development tips – DevOps :)
Also, it’s recommended to try to avoid catching exceptions in PHP. Exception handling can cause a performance penalty: Checking the performance of PHP exceptions, Speed performance of Trying and catching Exceptions in PHP.
When you develop WordPress websites for clients, and you want to host them yourself, you find yourself in a situation where you need to know a lot about systems administration “stuff“. Completely different topics than WordPress development. Like MySQL configuration, web server configuration, PHP settings, server security, and so on.
I often receive, and read about, questions from developers saying their hosting performance has degraded drastically over the course of time, and have no idea how to resolve the performance issues. In this optimized WordPress hosting post, I provided some important tips to improve hosting performance, for when you plan to host websites yourself.
If you have a valuable tip, please do share! And don’t forget to share this post with your friends and co-workers, thanks!