#8. Use Image Thumbnails
When you insert an image into WordPress it is inserted at the full image size. I recommend reducing the image size down to a smaller size for the post. The user can then simply click on the image to view the full sized version. To set thumbnail sizes that should be created go to Settings >> Media in the WordPress Admin area. Choose the sizes that your small, medium and large thumbnails should be. Then to insert a thumbnail simply change the size option to one of the thumbnails when adding or editing the image.
#9. Use a Minifier
A minifier WordPress plugin can be used to help optimize CSS and Javascript code being used on your site. A minifier works by rewriting the CSS or Javascript code down so that its text size is much smaller. This reduces the amount of data that needs to be sent over the internet. There are various minifiers available as plugins and I recommend trying out Autoptimize.
After using a minification plugin you must check that your site functions properly. In some cases minification can break some sites. But don’t worry as changes can be undone simply by removing or turning off the options in the minification plugin.
#10. Add Far Future Expiration for Web Browser Caches
Far Future Expiration sets how long a users web browser will locally cache content. When a user who has locally cached content reloads your page, that content will be served from the users local machine. Generally, we want things like images, icons and fonts to be cached for a long time, like maybe a month or more. Add this to your .htaccess file to enable far future expiration.
# BEGIN Far Future Expiration
<IfModule mod_expires.c>
ExpiresActive on
<FilesMatch "\.(gif|jpeg|jpg|png|ico|woff)$">
ExpiresDefault "access plus 720 hours"
</FilesMatch>
# CSS
ExpiresByType text/css "access 24 hours"
# Javascript
ExpiresByType application/javascript "access plus 24 hours"
</IfModule>
# END Far Future Expiration
#11. Delete Unused Plugins
Every plugin you add to WordPress increases it’s load time. Some more than others. Make sure you are only using plugins that you absolutely need and uninstall any that you are not using.
#12. Use P3 Plugin Profiler
P3 Plugin Profiler is a WordPress plugin that will analyze each plugin you have installed and determine how much CPU time they take up per page load. By using this profiler you can identify any plugins that are causing noticeable performance issues.
#13. Use YouTube Lyte
If you place YouTube videos on your blog you should use the YouTube Lyte plugin. This plugin ‘lazy loads’ the slightly bloated YouTube media player. Lazy loading means that the YouTube media player will only load when the user clicks on the video to watch it. Before that point a simpler lighter display only version of the YouTube media player is shown.
This plugin is especially useful and can make a huge difference if you have multiple YouTube videos per page.
#14. Delete Comment Spam Folder
Another major issue was that with the new found popularity spam bots had begun hitting the site pretty hard. After a month of neglect, my comment spam folder had over 6,000 spam comments marked by Askismet waiting to be cleared. A large amount of comments in the spam folder will increase the comment database size making it slow to access. To fix this simply delete all spam comments from your spam folder.
#15. Set Askismet to Delete Spam Straight Away
If you are using Askismet then to prevent the spam folder from growing too large again I set the Askismet strictness setting to “Silently discard the worst and most pervasive spam so I never see it.” Askismet is a free service that will detect and filter spam comments into your comments spam folder. Though for me at least I find that Askismet causes a lot of false positives. Instead I use a combination of Cookies for Comments (below) and WP-No-Bot-Question to stop spam.
#16. Use the Cookies for Comments Plugin
Although Askismet catches most spam comments it still lets some through every now and then. The plugin “Cookies for Comments” is a highly effective method at stopping comment spam. Essentially it works using two methods. One is that it checks for the presence of cookie that it sets. Spam comment bots often do not store cookies. Secondly, it treats any comment that was posted within X seconds of a page load as spam as it is unlikely that a human would post a comment so fast.
Be sure to add the recommended code to your .htaccess file as this will stop spam bots from even entering your site and eating up precious resources.
An alternative to Cookies for Comments that might work even better at stopping spam is Spam Destroyer. As well as the cookie technique spam destroyer requires the presence of Javascript, which many bots do not have enabled. Although, with Spam Destroyer you cannot block bots through your .htaccess file.
#17. Block XMLRPC Requests
After the site got popular when looking at my server logs one thing that I noticed was an inordinate amount of XMLRPC requests coming through. These requests were eating up significant CPU time and causing large slowdowns. This was probably caused by some sort of malicious bot trying to spam pingbacks or take down the site.
XMLRPC is used by the trackback and pingback functions of WordPress. Some plugins like Jetpack also require it. As I didn’t really need these functions I decided to simply block all XMLRPC requests. This can be done by editing your sites .htaccess file and adding the following code to the top of it.
ErrorDocument 503 "System Undergoing Maintenance"
RewriteEngine On
RewriteCond %{THE_REQUEST} "/xmlrpc.php" [NC]
RewriteRule .* - [R=503,L]
After blocking these spammy requests the server CPU usage went down and the site started loading faster.
#18. Stop WP-Login Attacks
WP-Login attacks are run by bots who attempt to bruteforce their way into your Wordpress account through the WP-Login admin page by guessing passwords many times a second. These attacks can hammer a site causing excessive CPU usage. I recommend using the Security-protection plugin to stop these attacks. WP-Security is my pick as it tricks the bot into believing that it has gained entry thus stopping the attack early and saving you from excessive server load. As a security tip I also recommend not using the ‘admin’ username for your account as the bots often only check this username.
If you have admin access to your server I also recommend setting up a fail2ban jail to stop these attacks.
#19. Use Fail2Ban to stop Repeat Spammers
By using fail2ban together with a WordPress spam logging plugin we can block repeat spammers at the firewall level. This will stop repeat spammers hammering your site and eating up precious resources. This is really only needed if your website it being targeted by aggressive spam bots which try and post a new spam message every few minutes. I used this tutorial to implement fail2ban spam protection.
#20. Install Mod_Evasive
Mod_evasive is a tool that will help your server to evade denial of service (DOS) attacks. If one of these attacks occurs on your server you hosted sites will take a massive performance hit. Mod_evasive blocks access to any IP that is DOSing your site.
#21. Serve Images Directly
I found a modification to the WordPress .htaccess file which will allow images to be served directly without invoking WordPress at all. Credit goes to this post by Rod Holmes. In your .htaccess file find the following
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
and replace it with the following
RewriteEngine on
#
# Unless you have set a different RewriteBase preceding this point, you may delete or comment-out the following RewriteBase directive:
#RewriteBase /
#
# if request is for image, css, or js file
RewriteCond %{REQUEST_FILENAME} \.(png|gif|jpe?g|css|js|ico)$ [NC,OR]
# or if URL resolves to existing file
RewriteCond %{REQUEST_FILENAME} -f [OR]
# or if URL resolves to existing directory
RewriteCond %{REQUEST_FILENAME} -d
# then skip the rewrite to WP
RewriteRule ^ - [S=1]
# else rewrite the request to WP
RewriteRule . /index.php [L]
#22. Upgrade PHP
Many servers are still running PHP 5.3 which has been declared end of life. Significant speed gains can be found by using the latest PHP 5.5 or 5.4. PHP 5.5 now has the Zend opcache built in which is a method that is used to significantly speed up PHP requests through code caching.
On some hosts with cPanel, upgrading PHP is a simple matter of going to Advanced >> PHP Configuration and changing the default PHP to 5.5. Note that after upgrading you will need to check your websites functionality as upgrades can sometimes cause problems.
#23. Use the latest WordPress
WordPress is constantly under development and new versions are released every few months. Usually new versions bring improvements such as speed boosts.
#24. Control Post Revisions
Every time you make a change to a post or page WordPress stores a revision copy just in case you need to go back to an old revision. By default WordPress stores ALL revisions you make. So if you edit your posts a lot there could be dozens of revisions taking up database space. I recommend you install the Revision Control plugin which will control the number of revisions kept. Set the number of revisions to how many you think you’ll need. In my case I chose to only keep 3 revisions at a time.
#25. Stop No-Referrer Comment Spam and Login Attacks
We can block spam bots and hackers brute forcing their way into the wp-login page with simple .htaccess file code. When a bot tried to access a page, it will usually try to access it directly without first visiting your site. If this happens we can detect it and block access to the bot with the .htaccess code below. Unfortunately, this isn’t effective as it used to be as modern advanced bots will get around this, but it will still stop many bots using simpler methods.
# Stop spam attack logins and comments
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_METHOD} POST
RewriteCond %{REQUEST_URI} .(wp-comments-post|wp-login)\.php*
RewriteCond %{HTTP_REFERER} !.*YOUR_DOMAIN.com.* [OR]
RewriteCond %{HTTP_USER_AGENT} ^$
RewriteRule (.*) http://%{REMOTE_ADDR}/$ [R=301,L]
</IfModule>