10 ways to speed up your WordPress website

A slow website is painful to use, less engaging to visitors, and hurts your search engine rankings. I’ll walk you through the tools I use to identify performance problems, and provide ten tips to improve your website’s performance.

You don’t need a WordPress Developer

I’ve written this article to help website owners improve their website’s performance on their own. You can implement most of these changes yourself or with your website host’s help.

You should see substantial speed improvements after implementing even a few of these recommendations. You don’t need to do everything on this list.

If you need help implementing these performance improvements, I recommend you speak with WP Buffs. They specialize in speeding up WordPress websites and keeping them fast over the long term.

If you would like a performance-focused redesign of your website, please contact me. Here’s some information on our process.

Quick Links to the Ten Tips

  1. Caching
  2. Image Compression
  3. High Quality Hosting
  4. Plugin Audit
  5. Minify CSS and JS
  6. Cache static content
  7. Use a CDN
  8. Clean up options table
  9. Decrease markup
  10. Decrease external requests

Before we get to the tips, I’d like to describe what makes a website slow. I’ll then show you how to diagnose what’s wrong with your website so you know which of these tips will be most effective.


What makes a WordPress website slow?

I like to break performance issues into two groups:

Backend Issues

I describe “backend issues” as issues that happen before and during the page generation on the server.

WordPress is a database-driven content management system. Your home page doesn’t exist as a static file on your server. It’s dynamically built using theme files, plugins, and database queries (ex: building menus, post content, sidebar widgets…).

Backend performance issues are usually caused by:

  • Poor hosting
  • Overloaded server
  • Complicated queries
  • Poorly written theme / plugins

In the performance report described below, a long Time To First Byte (TTFB) indicates backend issues. TTFB records the time from the initial request to when your server is done processing and starts sending data to the visitor.

The easiest improvements are to get better hosting and eliminate unnecessary plugins. Beyond that, these issues become more difficult for a non-technical person to solve on their own. Luckily you can cover up much of your backend issues with full page caching.

Frontend Issues

I describe “frontend issues” as issues that occur while the page is loading. These issues are usually caused by:

  • Large file sizes (images, CSS, JS)
  • Many files
  • Slow delivery

These issues are easier to identify, and some are simple to solve, like compressing imagesminifying CSS, and removing unnecessary plugins. It becomes more difficult when your “necessary” plugin list is long and they’re responsible for most of your issues.

Diagnosing issues

WebPageTest is my favorite frontend performance testing tool. You can drop in the URL of any website and get specific recommendations on improvements. You can also use Pingdom for a similar report.

Here’s an example of a speed test of my website.

They include letter grades at the top to summarize the results (A and B are good, D and F are bad). If you have a D or F for “First Byte Time”, that means you have backend issues. The rest are frontend / hosting issues.

Also pay attention to the “Fully Loaded” section. This summarizes the total time for your website to load, number of requests (different files that were loaded), total file size of the page, and a “cost” of delivering a site of that size (you want as few dollar signs as possible).

P3 Profiler lets you do a backend performance test of your site, focusing on the impact each plugin and your theme has on the load time. This is a great tool to quickly identify which plugins are causing issues.

Query Monitor lets you quickly see the number of queries run on a page, and how long each took to run. You can filter them by type, component (WP core, specific plugins) and sort by most time consuming.


10 ways to speed up your WordPress website

1. Caching

The simplest change most WordPress websites could benefit from is to use full page caching.

As described above, WordPress goes through a lot of work to build each page of your site. Every time someone asks to see your homepage, it does many queries and runs lots of code across WP core, your theme, and your active plugins.

But most of the time the page doesn’t change – it’s the same as the last time it was requested. Instead of generating it fresh for every visit, you can build it once, cache it, and serve the cached file every time someone requests that page. The cache expires periodically (every few hours), and is automatically cleared any time you edit the page.

Even if you have serious backend performance issues, most of your users won’t notice since they’re not interacting with your database at all – they’re downloading the static copy of your site. That isn’t to say you can ignore backend performance issues, but hiding it with caching can be a short-term solution.

High quality hosts like WPEngine have full page caching built-in, but on other hosts you’ll want to use WP Rocket (my recommendation, $39) or W3 Total Cache (free).

Even with WPEngine, I recommend WP Rocket because it addresses many of the other performance tips listed below.

If you’re a WordPress developer, I recommend you also consider fragment caching for complex queries or external API requests. While the full page cache might get rebuilt 5-10 times a day, you can cache the most expensive queries for longer using a transient, specifying exactly how often you want to refresh it. Here’s a great article on WordPress transients.

Let’s say your homepage uses a complex query to gather featured posts. Instead of running this every time the homepage is built, you could use a transient to refresh it once a day.

2. Image Compression

This is such an easy win! Most websites are using large, uncompressed images. You can reduce the image file size by 20-80% with no visual change. WebPageTest will tell you your potential savings from compression on the performance review tab (screenshot).

Go to your website right now and save an image. Then go to TinyPNG.com and upload it. See how much you could save. Now download the compressed image and open it with the original. Can you tell a difference?

You could manually upload every image to TinyPNG and download it before uploading it to your site, but that’s a hassle. I recommend installing the TinyPNG WordPress plugin and getting an API key. You get 500 free compressions per month which is plenty for most of my clients. You can also try other plugins like Optimus, WP Smush, and Imagify.

If you’re loading lots of images on your pages, you may consider lazy loading, which will wait to load the image when the visitor is close to seeing it.

You should also make sure you’re loading properly sized images throughout your site. I saw a site once with an archive page that had 300px wide images, but it was loading the original image file which was often 1600px wide or more.

3. High Quality Hosting

Your website can only be as fast as the server you host it on. If you’re using cheap, generic, $2/month hosting, you could follow all of these tips and still have trouble reaching the level of performance you’d like.

I recommend using a WordPress managed host like WPEngine ($35/month), LiquidWeb ($99/month), or SiteGround ($12/month). Here’s more information on my hosting recommendations.

Make sure your host is using PHP 7 or higher. Upgrading to PHP 7 will give you a large performance boost without any other changes on your site. Use the Display PHP Version plugin to find out what version of PHP you currently have, and the PHP Compatibility Checker plugin to ensure your current theme and plugins are compatible.

4. Plugin Audit

You’re probably aware that some of your plugins are causing performance issues, but not sure which ones. You can do a simple plugin audit yourself, or hire a WordPress developer, or ask your website’s host. Here’s Chris Lema from LiquidWeb:

First, clone your site to a staging environment. This will allow you to test changes without affecting your live website.

Go to the plugins page in the backend of your website. Deactivate any plugins you no longer use. Make a list of the active plugins that are absolutely essential to your site (ex: your membership plugin), those that provide a feature you need but aren’t necessarily unique (ex: social sharing plugins), and those that are optional.

Use P3 Profiler to see how each plugin affects the load time of your site. Also view the source code of the key pages on your site and search for wp-content/plugins to see the number and size of the CSS and JS files loaded by that plugin.

Browse your staging site with Debug Bar and Query Monitor, looking for errors and large / excessive queries. Dig into the details to determine which plugins are responsible for these errors & queries.

Remove all of the optional plugins that negatively affect performance or are loading too many assets. For the non-unique plugins that negatively affect performance, research other plugins that could provide similar functionality.

Using the staging site, disable plugins to see their affect on your site. Try installing alternative plugins and re-running your performance tests to see the effect of the change.

Sometimes you’ll be lucky and the results are straightforward. Some unused plugin is responsible for 80% of your load time, so you simply remove it. Other times you may need to hire a WordPress developer to do more extensive auditing and make recommendations for improvements.

Here’s a list of the plugins I use on most websites, which help maintain or improve the overall performance of the site.

5. Minify CSS & JavaScript

Once you’ve eliminated all the plugins you don’t need, it’s time to optimize the ones you have.

Plugins and themes load CSS and JS files to implement their functionality. They often leave these files “human readable” with lots of space and inline comments. This increases the file size you’re serving up for no good reason – your site visitors don’t need to read the CSS or JS files. To “minify” the files is to remove the extraneous data, often reducing the file size by 25-50%.

Some caching plugins will minify files for you, like WP Rocket. You can also use a separate plugin for this, like Autoptimize. If you’re using CloudFlare as a CDN (see below), they will also minify your assets for you.

You should have no problem combining CSS files. JavaScript files can be a bit more tricky. You may have conflicts combining certain JavaScript files. Some plugins may be adding JavaScript in the head of the page, but your combined file appears in the footer, which causes the plugin’s functionality to not work. If you do plan to combine JS files, test it extensively on your staging site.

6. Cache static content

Now that we’ve minimized the size and number of assets loading on your site, we should tell browsers to keep those locally cached for a long time.

If you’re using WP Rocket, it will take care of this for you. If you need to manually implement it yourself, add the following to your .htaccess file, or ask your host to do it for you:

<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/gif A31536000
ExpiresByType image/jpg A31536000
ExpiresByType image/jpeg A31536000
ExpiresByType image/png A31536000
ExpiresByType image/bmp A31536000
ExpiresByType text/css A31536000
ExpiresByType text/javascript A31536000
ExpiresByType application/javascript A31536000
ExpiresByType application/x-javascript A31536000
</IfModule>

7. Use a CDN

Your images, CSS, and JS files represent the majority of your site’s file size. You can deliver these much faster by offloading them to a CDN. A Content Delivery Network (CDN) is a geographically diverse group of servers designed specifically to deliver assets like these.

CloudFlare offers a CDN as part of their free plan. They also offer many other performance-enhancing features, so are worth reviewing. Here’s a detailed article reviewing CloudFlare’s performance offerings.

WP Rocket integrates directly with CloudFlare, so if you’re using WP Rocket, follow this tutorial to set up Cloudflare CDN. WP Rocket also integrates with many other CDNs.

If you’re using WPEngine for hosting, they include an optional CDN with all their plans. Here’s more information on WPEngine’s CDN, and information on integrating WPEngine’s CDN with WP Rocket.

Jetpack also includes a CDN for images, but not your other assets. If you’re using this plugin, make sure “Serve images from our servers” is checked (it’s on by default). Here’s more information about Jetpack’s Image CDN.

8. Clean up options table

This is a technical change that should only be done by a developer.

The options table is where WordPress core and plugins store site-wide data. Much of this data is set to “autoload”, which means it is loaded on every page of your site.

On older sites you’ll often find the options table filled with data for plugins no longer active. When I’m redesigning a site, I try to always review the options table and prune out the data associated with plugins no longer used.

The best place to start is to find large options and the largest autoloaded options. Here’s an example of the 10 largest autoloaded options on a site I’m redesigning, and what I’m planning to remove:

  1. Remove GooglePublisherPlugin – This is by far the largest option, ten times larger than #2. This plugin isn’t even installed on the site and looks like it’s no longer active.
  2. Keep rewrite_rules – This is a core WordPress option that tells WordPress how you’d like your permalinks.
  3. Keep wp_ubwqqt_user_roles – This is a core WP option that describes the roles for registered users in the site
  4. Remove yuzo_related_post_options – We’re building our own related posts query in the theme and won’t be using the Yuzo plugin.
  5. Remove redux_builder_amp – We’re not using the AMP plugin that created this option
  6. Keep widget_custom_html – This is a core WP option
  7. Keep wpseo_titles – This is set by Yoast SEO (formerly WordPress SEO)
  8. Keep cron – This is a core WP option
  9. Remove mashsb_settings – We replaced the Mash Share Buttons plugin with Shared Counts
  10. Remove sm_options – This is from an unused plugin (Google XML Sitemaps), which the client replaced a while ago with similar functionality in Yoast SEO

9. Decrease markup

One often overlooked area of optimization is the HTML markup. View the source of your key pages and look at the underlying markup. Are you surprised by how much HTML is associated with certain features of your site? Could those features be built more efficiently, or are they necessary at all?

WordPress is quite generous with the CSS classes it provides, and they can add up. I worked on a website a few years ago that had a large menu (about 80 items), and roughly 30% of the overall HTML markup was just the menu. By decreasing the unnecessary CSS classes, we were able to drastically shrink the markup.

Depending on the situation, I whitelist menu item classes or blacklist menu item classes. The blacklist approach ensures the “Custom CSS Class” feature in the menu editor continues to work, so is best if you are adding custom classes. You can do the same for post classes.

Once you’ve removed the unnecessary markup, you can compress the remaining HTML using WP Rocket or Autoptimize. Like CSS/JS minification, HTML often has extra space and comments that be safely removed, reducing the size of the page without removing any actual HTML markup.

10. Decrease external requests

One final way to improve the speed of your site is to reduce the requests your site makes for external resources. You should try to reduce total requests on your site as well, but external requests require an additional DNS lookup and you can’t improve the speed of a resource you don’t control.

When doing a performance review of a client site recently, we found their Twitter widget showing recent tweets was slowing the site down quite a bit. It was loading lots of images, about 30 totaling 2.9MB. By removing the Twitter widget we dropped the page size by more than 50% and cut the page load time to less than 2 seconds.

If you have Gravatars enabled (Globally Recognized Avatars), you could be loading a separate image for every comment on your site, drastically increasing the size and load time of your popular posts.  Here’s how to disable avatars in comments.

Many social sharing plugins load their buttons directly from the social networks, increasing the number of external requests. Shared Counts uses on-site buttons and leverages smart caching to to minimize the number of requests required to retrieve share counts.

You can use the Domains tab of the WebPageTest report to see the number of requests you’re making across each domain.

Your Turn

Do you have any tips to improve site speed? Share them in the comments below.

Bill Erickson

Bill Erickson is the co-founder and lead developer at CultivateWP, a WordPress agency focusing on high performance sites for web publishers.

About Me
Ready to upgrade your website?

I build custom WordPress websites that look great and are easy to manage.

Let's Talk

Reader Interactions

Comments are closed. Continue the conversation with me on Twitter: @billerickson

Comments

  1. rpk says

    In regards of point 5 a brief remark. Concatenation is only a recommended pattern for HTTP/1.1, for h2 it is more of an anti pattern. Best regards r.

  2. Will Stocks says

    Some great points here! I have been working on optimising my own blog over the past few weeks. A couple of extra, nitpicking items I reckon it’s worth looking at:

    1) Serve icon webfonts locally and only serve the icons you need. I shaved my icon webfont down from the standard 150KB WOFF2 to 12KB by simply removing icons from the file that I wasn’t using! Also saved me an external call/multiple external calls.

    2) When using autoptimize, make sure that CSS/JS that is used for most/all pages is included. I had a few files that only loaded on a single page (Contact Form type stuff) included by default, when those pages were “rarely” visited. It only trimmed off a few KBs, but when you have thousands of visitors per day, it all adds up to a fair bit of bandwidth!!

    3) I now serve gravatars locally. Means I can still use them, but no long have the slow/multiple calls out for the gravatars. I’m setup to regularly check for updates Gravatars. Bonus: author gravatars are cached and I can lazy load them! Plugin I use: Optimum Gravatar Cache.

    4) Lazy load images! Can’t tell you how much quicker this makes initial page load feel, as well as saves end users bandwidth if they don’t scroll through your whole page. Some themes include it, some don’t. A3 Lazy Load (plug-in) has always worked well for me when a theme doesn’t include it.

    5) Async JS/scripts that can load asynchronously, or defer scripts that can be deferred. I found I also didn’t need jquery-migrate, so dequeued that as well.

    6) Make sure your mobile site (/responsive site) is quick…. ESPECIALLY with Google’s new “mobile first” indexing. That means responsive images, remove anything that isn’t absolutely necessary, lazy loading, minimal requests, minimal content size, minimal UX/UI issues.

    I did most of the items you mentioned, plus those I mentioned above and dropped my full load time from 5+ seconds & 80+ requests down to under 2 seconds & 35 requests – including Adsense (most of the time)! https://www.webpagetest.org/ Is my go to for performance testing, with a dabble of https://gtmetrix.com/ 😊

  3. Dave Glick says

    The theme has a lot to do with it as well. Avada is really slow for example, Divi on the other hand is quite fast.

  4. TD says

    Bill,

    excellent article as usual. Thanks for pointing out the options table. A great opportunity for me to explore.

    Some items I have learned along the way, which may be of value to others.

    1. If you haven’t moved to HTTP/2 try to. This will require you first going to HTTPS. From there, you’ll need to figure out your host assets. I ran into a scenario where we upgraded, but the client’s theme wouldn’t work with specific PHP version. I guess the subrule is to have a test environment. On second thought, make that an Uber rule.

    A caveat to this rule is you need to rethink all the previous rules you learned about combining/minifying the number of CSS files, sprites, and older optimatization techinques. You need to test with your host (and CDN) to see what holds true. Test…test…test. No one knows your site better than you. HTTP/2 is a different scenario.

    Another side point is PHP versions. Please move to PHP 7 or higher if you can.

    2. When using webpagetest.org, under the Advanced Setting tab, use 9 for the Number of Tests to Run. This tip came from Pat Meehan who created the site. Too much variability if you use low numbers. Create an account with these guys so you can refer info back to your hosting provider. One of the many benefits of WebPageTest is you can keep historical data on an URL level.

    If you’re not familiar with WebPAgeTest, I found value in these articles

    https://moz.com/blog/the-seo-experts-guide-to-web-performance-using-webpagetest
    https://moz.com/blog/the-seo-professional-s-guide-to-waterfall-diagrams

    3. Again on WebPageTest.org, click the Image Analysis link under the grade scores. It links to Cloudinary and can give you nice optimization info on images unless you use lazy loading. Trust me there are more image formats that you never knew you didn’t know.

    4. Disclaimer…I’m not a programmer like Bill (yet). However, I also use a paid plugin called PerfMatters. Granted it has duplication in some area of optimization but I find it the easiest to turn off plugin scripts on a post/page basic. If you’re good at programming you could do this conditionally within WordPress. There is another plugin in from Gonzales, but I find this one easier.

    5. Make sure you don’t have plugins that duplicate or compete against your CDN. This is especailly true if you use a CDN that offers similar features. For example, you have similar minification settings with WP Rocket and CloudFlare. While the duplication may not hurt per se, I find it makes it more difficult when troubleshooting.

    6. I would suggest a JS plugin that allows you to specify, on per file basis, async vs defer. To give a real-world example, I encountered a bunch of AMP errors based on how a plug-in decided to use async vs defer.

  5. Jon Nastor says

    Hey Bill,

    Site speed is always on my mind so thanks for putting this together.

    As a non-dev, I struggle to keep my plugin usage to a minimum – although nothing like Chris’s client above! I am aware that not all plugins are created equally, but I still do use a couple iffy ones so I’m looking forward to giving P3 a shot and see what I should be looking to replace.

    Thanks!

    • Bill Erickson says

      All the tips above!

      The only one that won’t be as helpful is full page caching. Use Query Monitor to identify your most expensive queries (ex: related posts, custom menus) and store that data in a transient (see note on fragment caching above).

      Just make sure not to go too crazy with transients, like caching a different set of related posts for every post. Transients are stored in the options table, so if you start filling your database with large amounts of transients, you could do more harm than good.

  6. Hans Schuijff says

    Hi Bill,

    thanks for the tips. I now understand what transients are. 🙂 Thanks for the links. Is this subject the reason why you stopped offering the jetpack service to reminder commenters of replies? As a commenter I find that missing and liked being informed, while I now see several websites removing that service. So perhaps efficiency can also about removing customer/visitor-service?

    The websites that I run tend to be heavy (events + shop + learning management plugins and such) and I find that choosing to eliminate or add plugins not that easy. What is needed when there are all kinds of seo-requests, technical requests and functional requests? So I tend to end up anywhere between 60 and 72 plugins (a lot widely used premium plugins with their extensions). I ques a specialist or experienced developer would be able to optimize that more, but when we want to add multi-language it would mean even more plugins.

    Mostly good hosting and caching is used to make it workable and the most busy website has moved several times to make sure it can lift the load. At one point we used a themeforest LMS theme that was more integrated and had all kinds of options, but that had a high cost on loading time and the server, so now we are back using the genesis framework instead.

    Probably getting the balance right between functional demands, extra’s and speed will remain a challenge, but since 70% of users are on mobile, having all kinds of hover effect and such is no longer of value. Speed and simplicity as allway have.

    Cheers, Hans

  7. Device Reset says

    Many many thanks for this information. Last 1 month I search on google how to increase WP site speed, at last, I find my site problem solution and I really benefited from using this method. Care on to post more helpful article.

  8. Elena says

    Cleaning up options table is indeed a great and original idea. Do you know how much a huge autoloaded options would affect the load speed of a website?

  9. Bill Erickson says

    Autoloaded options are only an issue for uncached page requests since the cached ones don’t involve any DB requests. But that’s still an issue since quite a few visitors to your site will get uncached pages when the cache expires.

    You can quickly exhaust your server’s memory with large, autoloaded options. When you have Debug Bar installed, you’ll see the amount of memory required to build the page in the admin bar.

    Average memory required per page times the number of maximum concurrent users equals the minimum amount of memory your need in your server. If your page takes 10mb to load a page and you could have 100 visitors at once, you need 1GB of memory. If your page takes 100mb to load a page, you’ll need 10GB of memory.