You can probably tell “WordPress speed optimization” has become a joke, littered with paid blogs who recommend bad hosting, CDNs, and cache plugins so they can make commissions.
So let’s make a deal, K?
I will use 0 affiliate links in this tutorial. But if you find it helpful and actually trust what I say, you can find affiliate links in my reviews/tutorials in the nav menu. And no, you won’t see me recommending SiteGround, Hostinger, Kinsta, NitroPack, Elementor & Divi, or even WP Rocket. In fact, you’ll be seeing me provide quite a bit of evidence/sources why you shouldn’t use these.
I first published this guide in 2013 and have been keeping it updated ever since. So if you’re ready to fix your slow WordPress site with a detailed/honest tutorial, let’s jump straight into it.
Here are a few reports:
- Move your DNS to Cloudflare or QUIC
- Avoid most mainstream hosts
- Configure hosting settings
- Use Cloudflare APO, Enterprise, or QUIC.cloud
- Avoid page builders (or optimize them)
- Choose an image optimization setup (then optimize them)
- Configure a cache plugin that properly addresses web vitals
- Configure Perfmatters with your cache plugin
- Host third-party code locally, or delay it
- Preload files (preconnect/prefetch usually aren’t needed)
- Remove unused CSS the right way
- Learn how to check if a plugin is slow
- Disable plugins on specific pages
- Learn the 4 LCP sub-parts
- Avoid layout shifts
- Keep resource usage under 50%
- Get more database cleanup settings with WP-Optimize
- Optimize your mobile site
- List of speed plugins
- Hire my developer (Pronaya)
- My setup
1. Move Your DNS To Cloudflare Or QUIC
Test your site in this DNS speed test.
Cloudflare’s DNS performs well on dnsperf.com. But if you’re using a LiteSpeed server, use QUIC’s DNS since it gives you accurate geo-routing and better integration with QUIC’s CDN.
Your domain registrar is your DNS provider by default. Which means if you haven’t switched, you run the risk of a slow TTFB due to network latency, unscheduled DNS maintenance, and in worse case scenarios, your host’s DNS getting blocked by Google and losing your SEO rankings.
Hosts like Kinsta/Cloudways offer a premium DNS, but Kinsta uses Amazon Route 53 while Cloudways uses DNS Made Easy (which are both slower than Cloudflare). SiteGround requires you to use their DNS for their CDN, but have you seen their Google blocking fiasco on Twitter? Even for improving internet speed, changing your DNS to Cloudflare (1.1.1.1) is usually tip #1.
How To Change Your DNS To Cloudflare
Sign up for Cloudflare, add your website, and you’ll be prompted to change nameservers. Login to your domain registrar and find the setting to use custom nameservers, then add Cloudflare’s.
2. Avoid Most Mainstream Hosts
“Popular doesn’t mean better” is 100% true with hosting.
While there’s a lot of bad information out there, specs don’t lie. Several hosting companies dump money into being “recommended” everywhere. Like WordPress/Divi’s recommended hosts, Matthew Woodward’s WPX recommendation, SiteGround’s ties with Facebook Group admins who run multiple groups and promote their hosting, and Hostinger’s fake reviews.
Please, ignore the bogus “reviews” and look at the damn specs. Some specs are listed on the host’s website (or hidden on a separate page) while with others, you should ask them about it.
Specs of popular shared hosting plans:
SiteGround GrowBig | Hostinger Business WP | WPX Business | A2 Hosting Turbo Boost | NameHero Turbo Cloud | |
---|---|---|---|---|---|
Type | Shared | Shared | Shared | Shared | Shared |
Server | Apache + Nginx | LiteSpeed | LiteSpeed | LiteSpeed | LiteSpeed |
Cache plugin | SG Optimizer | LSC | LSC or W3TC | LSC | LSC |
CDN | Google Cloud | QUIC.cloud | QUIC.cloud / XDN | QUIC.cloud | QUIC.cloud |
Full page caching | ✓ | via QUIC | via QUIC | via QUIC | via QUIC |
DNS | Blocked by Google for 4 days | Internal / QUIC | Internal / QUIC | Internal / QUIC | Internal / QUIC |
Cores/RAM | Hidden | 2 cores/1.5GB | 1 core/1GB | 2 cores/2GB | 3 cores/3GB |
Storage | 20GB / SATA | 200GB / SATA | 15GB / SATA | “Unlimited” / NVMe | “Unlimited” / NVMe |
Object cache | Memcached | Memcached | x | Redis | Redis |
Database | MySQL | MariaDB | MariaDB | MariaDB | MariaDB |
Resource limits | CPU limits are common | Low resources | Low resources | Efficient with LiteSpeed | Efficient with LiteSpeed |
Inodes | 400,000 | 600,000 | At discretion | 600,000 | 500,000 |
Control panel | Site Tools | hPanel | WPX Panel | cPanel | cPanel |
Email storage | 10GB | 1GB | Many limits | Unlimited | Unlimited |
Major incidents | TTFB/DNS/CPU issues, unethical | Scam reports, fake reviews, 2019 breach | Global outage blamed on dead CEO | 2 week ransomware attack | 2 day node outage with apology letter |
Support | C | F | B | C | B |
TrustPilot rating | 4.6/5 | 4.6/5 (fake) | 4.9/5 | 4.4/5 | 4.6/5 |
Free migration | $30/site | Unlimited | 5 free | Unlimited | 1 free |
Intro price | $3.99/mo (1 year agreement) | $3.99/mo (2 year agreement) | $20.83/mo (1 year agreement) | $6.99/mo (3 year agreement) | $9.98/mo (3 year agreement) |
Renewals | $24.99/mo | $14.99/mo | $20.83/mo | $22.99/mo | $19.95/mo |
Specs | View | View | View | View | View |
Specs of popular cloud hosting plans:
SiteGround Cloud Jump Start Plan | WP Engine StartUp Plan | Kinsta Starter Plan | Cloudways Vultr HF (2GB) | Rocket.net Starter Plan | |
---|---|---|---|---|---|
Type | Cloud | Cloud | Cloud | Cloud | Private cloud |
Server | Apache + Nginx | Apache + Nginx | Apache + Nginx | Apache + Nginx | Apache + Nginx |
Cores/RAM | 4 cores/8GB | Not listed | 12 cores/8GB | 1 core/2GB | 32 cores/128GB |
Storage | 40GB / SATA | 10GB / SATA | 10GB / SATA | 64GB / NVMe | 10GB / NVMe |
CDN | Google Cloud | Cloudflare + Polish | Cloudflare + full page caching + firewall rules | Cloudflare Enterprise – APO ($5/mo) | Cloudflare Enterprise |
CDN bandwidth | Unmetered | Not listed | 100GB | 100GB | Unlimited |
DNS | Internal (previous issues) | Internal | Amazon Route 53 | DNS Made Easy ($5/mo) | Cloudflare |
Cache plugin | SG Optimizer | x | x | Breeze | x |
Object cache | Memcached | Memcached | Redis ($100/mo) | Redis Pro | Redis |
PHP processor | FastCGI | HHVM | FastCGI | FPM | LiteSpeed |
PHP workers | Not listed (but common issue) | Not listed (but common issue) | 2 PHP workers | No limit | No limit |
Memory limit | Adjustable | 512MB | 256MB | Adjustable | 1GB |
Database | MySQL | Not listed | Not listed | MariaDB | MariaDB |
Nginx reverse proxy | ✓ | Manual configuration | $50/mo | ✓ | ✓ |
Bandwidth or monthly visits | 5TB | 50GB + 25k visits/mo | 25k visits/mo | 2TB | 50GB + 250k visits/mo |
Email hosting | ✓ | x | x | x | x |
Malware removal | Scanner only | x | Removal pledge | x | Imunify360 |
Major incidents | TTFB/DNS/CPU issues, unethical | 2015 breach | None | None | None |
Migrations | $30/site | Paid (quoted) | Free (most hosts) | 1 free + $25/site | Unlimited free |
TrustPilot rating | 4.6/5 | 4.5/5 | 4.2/5 | 4.5/5 | 4.9/5 |
Price | $100/mo | $25/mo when paying yearly | $29/mo when paying yearly | $35/mo with CF Enterprise | $25/mo when paying yearly |
Sources
- SiteGround CPU limits are common, even on cloud plans.
- SiteGround bans people from FB Groups if they speak out about them.
- SiteGround threatens bloggers who write bad reviews (I also got a letter).
- SiteGround gets special treatment in FB Groups to promote their hosting.
- SiteGround’s community manager is an admin for the WP Speed Up Group.
- SG Optimizer does a poor job with web vitals (see “cache plugin” section).
- Hostinger email accounts use 1GB storage.
- Hostinger has multiple scam reports on Reddit.
- Hostinger’s CEO admitted employees write fake reviews.
- Hostinger’s 2019 security breach impacted 14M customers.
- WPX blamed a global outage on their partner’s dead CEO.
- WPX’s TOS doesn’t list all resource limits and many things are at their discretion.
- GoDaddy has low resource limits.
- GoDaddy experiences frequent data breaches (here’s the most recent one).
- GoDaddy’s charges for SSL, backups, and basic features in their catalog.
- NameHero’s experienced a 2 day outage and wrote a response.
- NameHero uses LiteSpeed and includes 15 free cPanel migrations.
- WP Engine had a data breach in 2015.
- WP Engine’s CDN is Cloudflare with Polish.
- WP Engine’s Nginx reverse proxy requires manual configuration.
- Kinsta lists CPU cores/RAM on a separate page and staging sites get 1 core.
- Kinsta’s charges $100/mo Redis, $50/mo Nginx reverse proxy, other add-ons.
- Kinsta says they use “an enterprise-level Cloudflare integration” when it’s not.
- Kinsta uses Amazon Route 53’s DNS which is slower than Cloudflare on dnsperf.
- Cloudways uses NVMe storage on Vultr HF and DO Premium.
- Cloudways uses Redis Object Cache Pro.
- Cloudways said APO will be launched soon, but still hasn’t nearly 1 year later.
- Rocket.net uses 32 cores/128GB RAM and switched to NVMe SSDs.
- *Many of these can be found on your host’s pricing table.
- *I also contacted several of them if something wasn’t listed.
There are plenty of other hosts/control panels, but there’s much more than what they tell you on the surface. Search Reddit forums, unbiased Facebook groups, and just be careful out there.
I would stick to one of these:
- LiteSpeed setup (LiteSpeed server + LiteSpeed Cache + QUIC.cloud).
- Control panels (i.e. RunCloud/Cloudways) with a VPS like Vultr or DigitalOcean.
- Managed cloud hosting (i.e. Rocket.net/Servebolt) which are also more hands-off.
3. Configure Hosting Settings
You should be able to find similar settings in your hosting account, or at least some of them.
- Caching layers – if they have something like Varnish or Nginx caching, use it.
- Redis/Memcached – Redis has advantages, and Redis Object Cache Pro is even better. Once enabled in your hosting account, you may need to connect it using your cache plugin (LSC/W3TC) or a Redis plugin. See your host’s documentation.
- OPcache – improves PHP performance and can also reduce CPU usage, so use it.
- PHP Version – use the latest version as long as your site/plugins are compatible.
- Brotli – not many hosts support Brotli (most use Gzip), but it’s a bonus if they do.
- Cron Jobs – replace wp-cron with a real cron job (most hosts have documentation on this). Aim for 5 or 10 minute intervals since something like “60 minutes” means all scheduled tasks in the past hour will run at the same and can cause CPU spikes.
- Hotlink protection – stops people from copying your images onto their website when they’re still hosted on your server (can be enabled in your host/Cloudflare).
- Memory limit – depends on how much memory you use, but 1024M is usually safe. Some hosts like Cloudways use PHP-FPM and have PHP-FPM memory limits.
- TLS – if your host has TLS settings, use TLS 1.3 and set minimum version to 1.2.
- Resource usage – just a reminder to keep an eye on resource usage & errors logs.
4. Use Cloudflare APO, Enterprise, Or QUIC.cloud
No reason to use anything but Cloudflare, unless it’s QUIC.cloud on LiteSpeed.
Some companies offer their own CDN (WP Rocket, SiteGround, WPX, etc). But why would you substitute Cloudflare’s massive network and extensive features for a CDN developed by less experienced teams (besides pay them instead of Cloudflare). Just like Cloudflare’s DNS on dnsperf.com, their CDN is a top performer on cdnperf.com with 192 Tbps data transfer speeds.
Cloudflare APO vs. Enterprise On Third-Party Services
Cloudflare with APO is fine for most sites, but you’re missing out on Enterprise features (specifically related to faster routing, image optimization, and an Enterprise-level firewall).
The problem is: while Cloudways, FlyingProxy, and Rocket.net all offer Cloudflare Enterprise, some of them lack features and it’s not “true Cloudflare Enterprise.” For example, Cloudways doesn’t support APO, FlyingProxy doesn’t support Argo (specifically good for WooCommerce), and Kinsta’s Cloudflare integration lacks way too many features to be considered “Enterprise.”
Out of the three, Rocket.net is the closest one to true Cloudflare Enterprise. Not only does it support both APO/Argo, but their CEO (Ben Gabler) was previously StackPath’s Chief Product Officer and has more CDN experience. It also works automatically without plugins, potentially resulting in 3 less plugins on your site between image optimization, security, and CDN plugins. Of course, I would take FlyingProxy over SiteGround’s CDN, RocketCDN, or BunnyCDN any day.
If you setup Cloudflare Enterprise on a third-party service, you do not need to configure your Cloudflare dashboard. This can be good because most integrations use better settings/rules than the average Joe, but it can be bad since last time I checked, Cloudways constantly served challenge pages. If you setup Cloudflare manually, you need to configure Cloudflare’s settings.
Cloudflare Free | Cloudflare Enterprise (Cloudways) | Cloudflare Enterprise (FlyingProxy) | Cloudflare Enterprise (Rocket.net) | |
---|---|---|---|---|
Tbps | 192 | 192 | 192 | 192 |
PoPs | 285 | 285 | 285 | 285 |
APO | $5/mo | x | ✓ | ✓ |
Argo Smart Routing | $5/mo + $.10/GB | ✓ | x | ✓ |
Prioritized routing | x | ✓ | ✓ | ✓ |
HTTP/3 | ✓ | ✓ | ✓ | ✓ |
WAF | ✓ | ✓ | ✓ | ✓ |
Load balancing | 500k queries free then 5 cents/500k | ✓ | ✓ | ✓ |
Mirage + Polish | x | ✓ | ✓ | ✓ |
Automatic configuration | x | x | x | ✓ |
Bandwidth | Unlimited | 100GB/mo | 100GB/mo | Depends on hosting plan |
Price | Free | $5/mo (1 domain) | $10/mo (1 domain) | Free w/ hosting |
Use QUIC’s Standard Plan On LiteSpeed
The only reason you shouldn’t use Cloudflare is if you’re on a LiteSpeed server, then use QUIC.cloud which is required for page/image optimizations in LiteSpeed Cache and supports HTML caching (similar to APO). However, you’ll want to use the standard plan which unlike the free plan, uses all 83 PoPs and DDoS protection. Once you setup QUIC, login to my.quic.cloud to upgrade to their standard plan, select your regions, add credits, and find various other settings.
RocketCDN (WP Rocket) | SiteGround CDN 2.0 (Paid Plan) | BunnyCDN | FlyingCDN (FlyingPress) | QUIC.cloud Standard Plan | |
---|---|---|---|---|---|
CDN | StackPath | SiteGround | BunnyCDN | BunnyCDN | QUIC |
Tbps | 100 | Not listed | 80 | 80 | Not listed |
PoPs | 73 | 176 | 114 | 114 | 79 |
Full page cache | x | ✓ | Geo-replication only ($.01 – $.005/GB) | Geo-replication only (included) | ✓ |
HTTP/3 | x | ✓ | x | x | ✓ |
Load balancing | x | ✓ | ✓ | ✓ | ✓ |
WAF | x | x | ✓ | ✓ | ✓ |
Anti-DDoS | x | x | ✓ | ✓ | ✓ |
Image optimization | x | Limited (see section #6) | Bunny Optimizer ($9.50/mo) | Bunny Optimizer (included) | ✓ |
Bandwidth | Not unlimited as advertised | Not unlimited as advertised | Unlimited | Unlimited | Unlimited |
Price | $8.99/mo | $7.49/mo | $.01 – .06/GB | $.03/GB | $.01 – .04/GB |
5. Avoid Page Builders (Or Optimize Them)
Page builders add extra CSS/JavaScript and increase memory usage.
The most dangerous part is what I’ll call the “page builder trap.” It’s when you install several extra page builder plugins (including Elementor Pro), then wonder why your site looks like this:
I’m not saying you can’t get 100% PageSpeed scores with Elementor, but you have to be very careful which hosting you use (I would go straight for a VPS), which plugins you install (always test CSS/JavaScript after you design a page with it), and make several other extra optimizations.
I switched to GeneratePress with GenerateBlocks and still use the Classic Editor to write posts. Kadence is good, but pricey. Then you have Oxygen/Breakdance, but they have a learning curve.
Page Builder Optimization Tips
- All performance settings should usually be on.
- CSS print method should be “external style.”
- Load Font Awesome 4 Support should be off.
- Google Fonts Load should (generally) be “swap.”
- Disable fonts/font icons and use custom fonts/icons.
- Regenerate files and data after changing these settings.
- Use less widgets/columns (here’s a YouTube video on it).
- Always test how much CSS & JS page builder plugins add.
- If plugins are module-based, disable modules you don’t use.
- Disable page builders plugins where they’re not used (see step #13).
- Disable Gutenberg’s CSS in Perfmatters or Asset CleanUp if you don’t use it.
- Code header/footer/sidebar in CSS (my developer can do this and helps a lot).
6. Choose An Image Optimization Setup (Then Optimize Them)
There are 3 big benefits of using image CDNs instead of plugins:
- Less taxing on your server (image optimization plugins use server resources).
- Less bloat (image optimization plugins usually store image variations/backups).
- Besides maybe Optimole, they usually include more image optimization features.
Imagify | ShortPixel | Optimole | SiteGround CDN | Bunny Optimizer | Cloudflare Mirage/Polish | |
---|---|---|---|---|---|---|
Compression | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
WebP | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
Mobile resizing | x | Requires ShortPixel Adaptive Images | ✓ | x | ✓ | ✓ |
Network optimizations | x | x | ✓ | x | x | ✓ |
AVIF conversion | x | ✓ | ✓ | x | x | ✓ |
AVIF support | x | ✓ | ✓ | x | x | ✓ |
Serve images from CDN | x | Requires ShortPixel Adaptive Images | Cloudfront | SiteGround CDN | ✓ | ✓ |
No server usage | x | x | x | x | ✓ | ✓ |
No bloat | x | x | Offload to cloud | x | ✓ | ✓ |
Price | Free 20MB/mo then $9.99/mo | Free 100 credits/mo then $3.99/mo | Free 5,000 visits/mo then $19.08/mo | Free ($7.49/mo for paid CDN) | $9.5/mo or $.03/GB w/ FlyingCDN | Included w/ Cloudflare Enterprises |
Depending on your setup, there may be other items to address:
Tips
- Resizing images – if you take screenshots, I use the Zoom Chrome Extension to get perfect screenshots without having to resize the image (which can reduce quality). Just take the screenshot, crop it, save it in WebP, and upload it. I also recommend creating a cheat sheet with the different image sizes for blog images, featured images, sidebars, Facebook/Twitter OG images (for social sharing), etc.
- Mobile resizing – use SP Adaptive Images if your plugin/CDN doesn’t support it.
- Lazy load background images – Elementor added a performance setting to do this which lazy loads all background images except the 1st one on the page. For Divi and other page builders, check if your optimization plugin does it: FlyingPress has a lazy-bg helper class, Perfmatters can lazy load CSS background images (then exclude the 1st one from lazy load with “perfmatters-lazy-css-bg” class), Optimal does it, and WP Rocket makes you move background images to inline HTML (ugh).
- Compress images at 85% – this is the compression level Lighthouse tests images.
- WebP – while most image CDNs support WebP, they don’t always convert them if the savings aren’t high enough (use Chrome Dev Tools to check if they are). But if you manually convert them using a free WebP converter, the savings can often be over 50%. That said, I recommend uploading images in WebP to begin with, or at least convert above the fold images to WebP since they’re most important for LCP.
- Exclude above the fold images from lazy load and preload them – since these images are seen first, you don’t want to lazy load them or it creates resource load delay. They should also be prioritized through preloading. The easiest way to do this is the 1-click setting in FlyingPress or Perfmatters. Otherwise, there are a few plugins like Preload Features Images, but you still need to exclude them from lazy load. WP Rocket’s helper plugin makes it easier or exclude them by URL, class, etc.
- Set browser cache TTL to 365 days – static assets (like images) should use a long cache expiration since they don’t change often. Google recommends 365 days (or 3153600 seconds). If changing Cloudflare’s browser cache TTL doesn’t work, check your hosting settings (i.e. static cache expiry in Cloudways). Since WooCommerce sites are dynamic, you would probably want to lower the TTL to around 1 month.
- Specify dimensions – most cache plugins “add missing dimensions” otherwise, add the width/height manually to the image’s HTML which prevents layout shifts.
7. Configure A Cache Plugin That Properly Addresses Web Vitals
NitroPack cheats scores and most free cache plugins lack many features for web vitals. But if I had to use one it would probably be Swift Performance or W3 Total Cache which are freemium.
Which leaves the following:
SG Optimizer | WP Rocket | LiteSpeed Cache | FlyingPress | |
---|---|---|---|---|
Server-side caching | ✓ | x | ✓ | x |
Delay JavaScript | x | ✓ | ✓ | ✓ |
Remove unused CSS | x | Inline | Separate file | Separate file |
Critical CSS | x | ✓ | ✓ | ✓ |
Preload critical images | x | x | By number | x |
Exclude above the fold images | Manual | Manual | Automatic | Automatic |
Lazy load background images | x | Inline | x | Helper class |
Lazy render HTML elements | x | x | ✓ | ✓ |
Add missing image dimensions | x | ✓ | ✓ | ✓ |
YouTube iframe preview image | x | ✓ | ✓ | ✓ |
Self-host YouTube placeholder | x | x | x | ✓ |
Host fonts locally | x | x | ✓ | ✓ |
Font-display: swap | x | ✓ | ✓ | ✓ |
Preload links | x | ✓ | ✓ | ✓ |
CDN | SiteGround CDN | StackPath | QUIC.cloud | BunnyCDN |
APO compatibility | x | x | ✓ | ✓ |
Price | Free | $59/yr | Free | $60/yr |
Renewal price | Free | $59/yr | Free | $42/yr |
Tutorial | View tutorial | View tutorial | View tutorial | View tutorial |
Use LiteSpeed Cache if you’re on a LiteSpeed server, FlyingPress in most other cases.
WP Rocket Is Falling Behind
WP Rocket only released 1 new feature after 2020 in their changelog. Compared to other plugins, it does a poor job optimizing LCP, images (even with Imagify), can’t host fonts locally, and RocketCDN is slow. Both FlyingPress and LiteSpeed Cache heavily rely on feedback from their community while WP Rocket seems to have gone stale. With increased prices and lacking features, I switched to FlyingPress and aside from web vitals, my site is also significantly faster.
Using SiteGround Optimizer With FlyingPress (Or WP Rocket)
SG Optimizer is fine for caching, but not web vitals, It also has ongoing compatibility issues support blames on third-party plugins. Only use it for the following features, then disable everything (including file-based caching) and use FlyingPress or WP Rocket for everything else.
- Dynamic caching
- Memcached
- Automatic purge
- HTTPS enforce
- GZIP compression
- Heartbeat optimization (keep disabled when using WP Rocket)
- Disable emojis
- Image compression/WebP (but ideally use an image CDN since this uses server resources)
Minify With Your Cache Plugin, And Don’t Combine
Even when using Cloudflare, they recommend minifying with your cache plugin instead of Cloudflare. The high majority of websites shouldn’t combine CSS/JavaScript since it usually makes your site slower and shouldn’t be done with HTTP/2 (which is used on most servers).
8. Configure Perfmatters With Your Cache Plugin
I’ll be mentioning Perfmatters quite a bit in this guide. Based on my knowledge and conversations with their team, here’s how to configure it with different cache plugins:
Perfmatters Setting | FlyingPress | LiteSpeed Cache | WP Rocket | SiteGround Optimizer |
---|---|---|---|---|
General | Enable all | Enable all but move wp-login + heartbeat | Enable all but heartbeat | Enable all but heartbeat |
Assets | Enable script manager | Enable script manager | Enable script manager + remove unused CSS (leave all CSS settings off in WP Rocket) | Enable script manager, delay JavaScript, remove unused CSS (leave all CSS settings off in SG Optimizer) |
Preloading | Preload CSS/JS files | Preload critical images and fonts/CSS/JS files | Preload critical images and CSS/JS files | Preload critical images and CSS/JS files |
Lazy Loading | Leave off (use FlyingPress’ lazy-bg class for backgrounds) | Enable CSS background images | Enable CSS background images | Enable all lazy load settings (turn lazy load off in SG Optimizer) |
Fonts | Leave off | Leave off | Enable local Google Fonts | Enable display swap + local Google Fonts |
CDN | Leave off (add CDN URL to FlyingPress) | Leave off (use QUIC) | Leave off (add CDN URL to WP Rocket) | Leave off (unless you have a CDN URL) |
Analytics | Leave off (delay instead) | Leave off (delay instead) | Leave off (delay instead) | Leave off (delay instead) |
FlyingPress + Perfmatters – configure FlyingPress normally and only use Perfmatters for the general settings, script manager, and preloading settings to preload files besides images/fonts.
LiteSpeed Cache + Perfmatters – configure LiteSpeed cache normally. Leave all settings off in Perfmatters except the general settings (but leave the Heartbeat setting off and don’t move wp-login since QUIC.cloud protects the wp-login URL). Use the Assets settings to enable the script manager. Use the preloading settings to preload files (including fonts, images, and preloading critical images). And finally, only use the lazy load settings to lazy load CSS background images.
WP Rocket + Perfmatters – configure WP Rocket normally, but disable all CSS settings. Leave all Perfmatters settings off except the general settings (but leave Heartbeat off). Use the Assets settings to enable the script manager and remove unused CSS. Use the preloading settings to preload critical images and preload files other than fonts/images. Use the lazy load settings to enable CSS background images. And finally, use the fonts settings to enable local Google Fonts.
SiteGround Optimizer + Perfmatters – configure SiteGround Optimizer normally, but disable all CSS and lazy load settings. Leave all Perfmatters settings off but the general settings (leave the Heartbeat setting off). Use the Assets settings for the script manager, delay JavaScript, and remove unused CSS. Use the preloading settings to preload files other than fonts/images, and preload critical images. Use all the lazy load settings to lazy load images and exclude leading images, iframes/videos, add missing images dimensions, and lazy load CSS background images (while using the perfmatters-lazy-css-bg helper class to exclude above the fold images). Use the fonts settings to display swap and use local Google Fonts. All 3 cache layers should be on in SG. These will be different when also using FlyingPress or WP Rocket – just avoid duplicate features.
Perfmatters already removes some bloat in the General settings, but if you want even more bloat removal options, try the Unbloater + Disable WooCommerce Bloat plugins.
9. Host Third-Party Code Locally, Or Delay It
View your third-party code report [screenshot]. A very common reason for third-party JavaScript is using too many analytics tools (overtracking). Otherwise, follow these 2 steps:
Step 1: Host Files Locally If Possible.
Third-party fonts, Google Analytics, Gravatars, and YouTube thumbnails can all be hosted locally. LiteSpeed Cache has a setting to localize resources and WP Rocket doesn’t support hosting files locally. The analytics settings in Perfmatters let you disable display features and use smaller analytics scripts, but this isn’t necessary if you plan on delaying Google Analytics.
While some cache plugins host fonts locally (FlyingPress), others do not (WP Rocket). In which case, you can upload custom fonts in Elementor, OMGF, or use Perfmatters’ local Google Fonts. Also make sure you’re using woff2 and remove font families, weights, and icons you don’t use. While system fonts are even faster (which create 0 requests), they don’t always look the nicest. And if you’re savvy, you can use Cloudflare Workers to optimize fonts using the code on GitHub.
Third-Party Code | URL Examples | Plugins To Host It Locally |
---|---|---|
Google Fonts | fonts.gstatic.com | FlyingPress, Perfmatters, OMGF |
Google Analytics | google-analytics.com | Perfmatters, Flying Analytics |
Gravatars | gravatar.com | Simple Local Avatar |
YouTube Thumbnails | i.ytimg.com | FlyingPress, WP YouTube Lyte |
Step 2: Delay Remaining Third-Party Code If It’s Shown Below The Fold.
Most optimization plugins can delay JavaScript (if not, use Flying Scripts). View your plugin’s documentation since the steps can be different for each plugin. For example, WP Rocket delays third-party JavaScript automatically while other plugins require you to add it manually. Below is a list of common JavaScript files you can delay. But again, check the plugin’s documentation.
ga( '
ga('
google-analytics.com/analytics.js
analytics.js
gtagv4.js
analytics-minimal.js
/gtm.js
/gtag/js
gtag(
/gtm-
adsbygoogle.js
grecaptcha.execute
optimize.js
fbevents.js
fbq(
/busting/facebook-tracking/
disqus.com/embed.js
script.hotjar.com
wp-content/themes/script-name
wp-content/plugins/plugin-name
10. Preload Files (Preconnect/Prefetch Usually Aren’t Needed)
- Preload – makes something “high priority” like above the fold fonts, images, etc.
- Preconnect – establishes early connections to third-party domains and should usually only be done with third-party fonts (fonts.gstatic.com) and CDN URLs. However, this is usually done automatically by cache plugins so you don’t need to, but check their docs.
- Prefetch – similar to preconnect but doesn’t involve TCP handshakes/TLS negotiations. You shouldn’t need to add prefetch hints since most third-party code is hosted locally or delayed, so early connecting to something that’s also being delayed doesn’t make sense.
Preload Fonts – just like you preload above the fold images since they’re shown immediately, it’s the same with fonts. View your waterfall chart, copy your font files (if they load above the fold) and preload them. Most cache plugins do this. If you use Perfmatters, also use crossorigin.
Preload Images – above the fold images should be excluded from lazy load and preloaded. To recap, FlyingPress + Perfmatters are best at this which have a setting to preload critical images.
Preload WP-Block-Library – If you use Gutenberg, a CSS file loads across your site (search “block-library” in your source code). Preload it by adding “wp-block-library” in Perfmatters.
Preload Links – most optimization plugins preload links (also known as “instant click”). Depending on the feature, this preloads pages in the viewport or when users hover over a link. So by the time they actually click it, those pages appear to load instantly. While this doesn’t improve scores, it improves perceived load time. Just be careful – if visitors hover over lots of links (i.e. WooCommerce product images), it can download lots of pages and stress your server.
HSTS Preload – submit your site to Chrome’s HSTS Preload list for a small performance boost. You can use that website to check if yours supports it and if not, try this plugin or ask your host.
Cloudflare Early Hints – Early Hints by Cloudflare sends preload/preconnect hints earlier to browsers to reduce server wait time. It’s found in your dashboard under Speed → Optimization.
11. Remove Unused CSS The Right Way
Do not use WP Rocket to remove unused CSS.
As Perfmatters says in the documentation, loading used CSS inline is better for scores (what WP Rocket does) while loading it in a separate file is faster for actual users (what FlyingPress, LiteSpeed Cache, and Perfmatters all do). Vikas, who is very active in Facebook Groups, agrees:
If you use WP Rocket, disable this feature (as well as all other CSS settings), then enable it in Perfmatters using “file” for used CSS method. I also confirmed this with Brian from Perfmatters.
12. Learn How To Check If A Plugin Is Slow
There are a few reasons a plugin can be considered slow:
Why It’s Slow | Test It Using: | Screenshot |
---|---|---|
Adds CSS/JS to frontend | Coverage report | View screenshot |
Increases memory usage | WP Hive | View screenshot |
Adds database bloat | WP-Optimize / phpMyAdmin | View screenshot |
Uses jQuery | Perfmatters display dependencies | View screenshot |
Plugin Optimization Tips
- Replace Plugins With CDNs, Blocks, Code – Cloudflare’s Mirage/Polish and WAF help you avoid image optimization/security plugins, Gutenberg blocks can replace things like tables/galleries/buttons, and coding a table of contents similar to mine isn’t that hard. Avoid mega menus and code your Elementor header/footer in CSS.
- Limit Background Tasks – security plugins, Wordfence’s live traffic report, Query Monitor, Broken Link Checker, image optimization plugins, and other background tasks increase memory usage and can slow down both the frontend and backend.
- Delay Plugins – if it loads content below the fold (i.e. third-party comments), try delaying it in FlyingPress using “wp-content/plugins/plugin-name” (see step #9).
- Disable Unused Features – especially true if they create database bloat or trigger background tasks. Also disable unused features if you have module-based plugins.
I also created a list of 75+ slow plugins.
Plugin | Category | Memory Impact | PageSpeed Impact |
---|---|---|---|
All In One SEO | SEO | x | x |
Broken Link Checker | SEO | x | ✓ |
Disqus | Comments | ✓ | x |
Divi Builder | Page Builder | x | x |
Elementor | Page Builder | x | x |
Elementor Premium Addons | Page Builder | ✓ | x |
Elementor Pro | Page Builder | x | x |
Elementor Ultimate Addons | Page Builder | ✓ | x |
JetElements | Page Builder | x | x |
Jetpack | Security | x | x |
NextGEN Gallery | Gallery | x | x |
Popup Builder | Popup | x | x |
Site Kit by Google | Analytics | x | ✓ |
Slider Revolution | Slider | x | x |
Social Media Share Buttons | Social Sharing | ✓ | x |
WooCommerce | WooCommerce | x | x |
Wordfence | Security | x | ✓ |
wpDiscuz | Comments | x | x |
WPML | Translate | x | x |
Yoast SEO | SEO | x | ✓ |
13. Disable Plugins On Specific Pages
Pefmatters (what I use) and Asset CleanUp are 2 popular options.
I prefer Perfmatters because it has more optimization settings (such as bloat removal), new features are released frequently, and the interface is also easier compared to Asset CleanUp.
Step 1: Enable The Script Manager And Test Mode – enable the script manager in the Assets settings. View any page on your site and in your top menu, click Perfmatters → Script Manager. Go to your script manager settings and enable test mode. This lets you test the script manager without it breaking your site (only logged-in admins will see changes). Disable it when you’re done to publish changes. Enable display dependencies if you want to see plugins using jQuery.
Step 2: Disable Plugins On Pages/Posts – view the script manager on a few pages/posts you think load different plugins, then use the settings to disable them everywhere but pages, posts, single URLs, or disable them on mobile devices, logged-in users, or Regex. If you disable plugins on mobile devices, you’ll need to enable “separate mobile cache” in your cache plugin settings.
Examples:
- Disable social sharing plugin everywhere but posts.
- Disable contact form plugin everywhere but contact page.
- Disable page builder plugins where they’re not being used.
- Disable Gutenberg’s CSS file if you’re not using Gutenberg.
- Disable email plugins on pages if you only use them on the blog.
- Disable WooCommerce plugins on non-eCommerce pages/posts.
14. Learn The 4 LCP Sub-Parts
LCP is divided into 4 sub-parts:
LCP Sub-Part | Factors | LCP % |
---|---|---|
TTFB | Hosting, CDN, full page caching, etc (test in KeyCDN/SpeedVitals) | ~40% |
Resource load delay | Preload fonts, viewport images, exclude viewport images from lazy | <10% |
Resource load time | Reduce image/CSS/JS sizes, critical CSS, CDN, cache expiration | ~40% |
Element render delay | Usually related to JavaScript (defer it, reduce it, unload it, etc) | <10% |
Open the performance report in Chrome Dev Tools and click “start profiling and reload page.” Highlight the main area (shown under step #2). Finally, view all files loading in your LCP time (shown bottom right) and you’ll be able to see which files (or TTFB) take longest to load. If the first request takes a long time (shown in blue as HTML), it’s probably because your TTFB is slow.
In other words, there’s a lot more to LCP than preloading an LCP image. A waterfall chart can help you understand whether TTFB or specific image/JS/CSS/font files are contributing to LCP.
Many LCP optimizations are covered in this guide: TTFB, preloading above the fold images and excluding them from lazy load, preloading fonts, reducing file sizes, font-display: swap, Brotli, and increasing browser cache TTL. Here are other optimizations:
- Move heavy files below the fold – this way, their JavaScript can be delayed.
- Cloudflare SXGs – found in your Cloudflare settings (Speed → Optimization).
- Cloudflare Workers – Google Engineer used them to improve LCP by about 80%.
- Defer JavaScript – prevents render-blocking JS which impacts render delay.
- Lazy render HTML elements – lets browsers focus on above the fold content and is support by FlyingPress/LiteSpeed Cache (#comments and #footer are common).
It’s also worth spending 30 minutes watching Google’s LCP tutorial:
15. Avoid Layout Shifts
Layout shifts happen when things jump around while the page loads which can be seen in PageSpeed Insights, Waterfall charts, Google’s layout shift debugger, and other speed tools.
Again, many layout shift optimizations are covered in this guide: font-display: swap, preloading fonts, and adding missing image dimensions. Here are other optimizations:
- Remove unused CSS – use this instead of “asynchronous CSS” in your cache plugin. Otherwise, it can cause layout shifts with FOUC. If removing CSS breaks your site, use asynchronous CSS but exclude problematic files causing FOUC, ensure critical CSS is working, and regenerate critical CSS if you edited the CSS.
- Add dimensions to ads/dynamic content – reserve space for dynamic content (like ads) by placing it in a div code (the width/height will be the ad’s largest size).
- Use CSS transform/translate in animations – since this is only supported in Elementor widgets, you can use Happy Addons to add a CSS transform property.
- Use separate mobile cache (when applicable) – if your mobile site is different than desktop, enable separate mobile cache in your cache plugin or it can create layout shifts. Also check your cache plugin’s documentation on when to use this.
- Change your cookie notice plugin – search the plugin’s support forums because it’s been reported some cookie plugins cause layout shifts. I use this Cookie plugin.
16. Keep Resource Usage Under 50%
Users can experience lag if CPU usage is high, usually 70+%. You also want to leave room for fluctuations like traffic spikes and background tasks. Disk space also shouldn’t be close to full.
Many CPU usage optimizations are covered in this guide: offloading bandwidth to your CDN, full page caching, object cache, OPcache, removing high memory usage plugins (and disabling unused features including plugin data sharing), Perfmatters’ general settings (disabling XML-RPC + Heartbeat, increasing the autosave interval, moving wp-login), using a firewall + bot protection to block unwanted requests, replacing wp-cron with a real cron job, and disabling link preloading if users are hovering over lots of links.
- Limit preloading in cache plugins – WP Rocket’s preloading, LiteSpeed Cache’s crawler, or SG Optimizer’s preheat cache can all increase CPU usage. Some can be controlled more than others. WP Rocket can only preload important sitemap URLs (page-sitemap.com and post-sitemap.com) and can increase the preload interval.
- Limit automatic cache clearing in cache plugins – there are specific actions that trigger your entire cache to clear (also if the cache lifespan expires). The better option is to disable automatic clearing and setup a cron job to clear it at a specific time (once at night). Cron jobs can be setup for cache clearing + cache preloading.
- Limit unused CSS batch size – decrease the batch size and increase cron interval.
- Protect your login page – common target for bots/hackers, so you should protect by either moving the wp-login page, with QUIC.cloud, and limiting login attempts.
- Spam comments – I’ve been using Antispam Bee since Akismet isn’t free anymore.
- Cores, RAM, resource limits – use a hosting plan with enough resources. Kinsta, Hostinger, and GoDaddy skimp on these, and know what their resource limits are.
- Try LiteSpeed – did you know LiteSpeed can handle 2x the capacity of Apache?
- Disable pingbacks/trackbacks – found in your WordPress discussion settings.
- Remove autoloaded data – plugins/themes can leave behind autoloaded data even when you delete them which can be cleaned up in your wp_options table.
- Disable data sharing – uses a small amount of resources, so disable it in plugins.
17. Get More Database Cleanup Settings With WP-Optimize
There are 3 problems with cleaning your database with most cache plugins:
- It can’t take database backups.
- It can’t remove database tables left behind by old plugins.
- It deletes all post revisions, but you probably want to keep a few.
That’s why I recommend WP Optimize for database cleanups. Go through your database tables and look for tables that are not installed or inactive. You can delete these if you don’t plan on using the plugin or theme again since they will usually store info in the database for future use.
Certain plugin features can add overhead, especially if they collect data. Consider disabling features like Rank Math’s analytics module and getting your data from Google Analytics directly.
For scheduled cleanups, WP-Optimize removes everything most cache plugins do, but keeps a certain amount of post revisions (5-10 is fine) and can take database backups with UpdraftPlus.
18. Optimize Your Mobile Site
Most desktop optimizations carry over to mobile, otherwise, here are mobile-specific tips.
Reducing latency is key for mobile users and part of TTFB. This is mainly related to your DNS/CDN and if it has features like full page caching, HTTP/3, Brotli, and Cloudflare’s 0-RTT.
The distance between users and CDN PoPs plays a big role, but is almost irrelevant with Cloudflare Enterprise between it’s large network, prioritized routing, Argo Smart Routing + Tiered Cache, and load balancing (so no need to choose a host based on their data centers).
Some CDNs have mobile and network-based optimizations. For example, resizing images for mobile is done with Cloudflare’s image resizing, Bunny Optimizer, and FlyingCDN (which uses Bunny Optimizer). Cloudflare/Optimole also downgrade image quality on slow connections.
Higher TLS versions have less latency than previous TLS versions. Cloudflare and Cloudways both have TLS settings where you should enable TLS 1.3 and set minimum version to TLS 1.2.
- Use mobile caching – enable this in your cache plugin or use one that supports it.
- Know when to use separate mobile cache – check your cache plugin docs since some settings like Guest Mode on LiteSpeed Cache require separate mobile cache.
- Fix mobile layout shifts – Google’s layout shift debugger can test CLS on mobile.
- Add a “load more comments” button – helps if you have lots of blog comments.
- Don’t use AMP – lots of challenges and most WordPress users agree not to use it.
- Remove unused CSS/JS – Perfmatters can disable unused CSS/JS by device type.
19. List Of Speed Plugins
Here’s the full list.
Obviously you don’t need all these, but some optimization plugins and CDNs lack certain features in which case, you may consider using extra plugins to address more optimizations.
Plugin | Category | Price |
---|---|---|
FlyingPress | Cache | Paid |
LiteSpeed Cache | Cache | Free |
Perfmatters | Multiple Categories | Paid |
Cloudflare | CDN | Paid |
Super Page Cache for Cloudflare | CDN | Free |
WP-Optimize | Database | Free |
FlyingProxy | CDN | Paid |
Flying Pages | Resource Hints | Free |
Flying Scripts | Delay JavaScript | Free |
Flying Analytics | Analytics | Free |
Optimole | Image | Freemium |
ShortPixel Adaptive Images | Image | Freemium |
WP YouTube Lyte | Video | Free |
OMGF | Font | Free |
WP Foft Loader | Font | Freemium |
Pre* Party Resource Hints | HSTS Resource Hints | Free |
Headers Security Advanced & HSTS WP | Resource Hints | Free |
WP Crontrol | Cron Job | Free |
Unbloater | Bloat Removal | Free |
Debloat | Bloat Removal | Free |
Disable WooCommerce Bloat | Bloat Removal | Free |
Heartbeat Control | Bloat Removal | Free |
Disable XML-RPC | Bloat Removal | Free |
Widget Disable | Bloat Removal | Free |
Limit Login Attempts | Security | Free |
WPS Hide Login | Security | Free |
Redis Object Cache | Cache | Free |
Blackhole For Bad Bots | Block Bots | Free |
Simple Local Avatars | Comments | Free |
Preload Featured Images | LCP | Free |
Query Monitor | Diagnostic | Free |
WP Server Health Stats | Diagnostic | Free |
WP Hosting Benchmark | Diagnostic | Free |
WP Hosting Performance Check | Diagnostic | Free |
20. Hire My Developer (Pronaya)
Still need help?
I’m not for hire… too many tutorials to write. But I’ve been working with Pronaya since 2012. He’s $40/hour and is still the best developer/speed optimizer I’ve worked with. He lives in Bangladesh (so there’s a time change), but his communication and work are always top notch.
He can help with:
- Configuring/migrating hosts, CDNs, cache plugins.
- Migrating your slow page builder to GeneratePress.
- Optimize fonts, hosting them locally, and reducing their size.
- Coding things in CSS like page builder headers/footers, TOC, etc.
- General speed optimizations, development work, troubleshooting.
DIY
- Search the WP Speed Matters Facebook Group.
- Plugins like Perfmatters have great documentation.
- Gijo Varghese and WP Johnny also put on quality articles.
- My other articles: if you liked this one, I have plenty more.
21. My Setup
This is what I use:
Service | Category | Price |
---|---|---|
Rocket.net | Hosting | Starts at $25/mo (yearly price) |
Cloudflare Enterprise | CDN | Free on Rocket.net |
FlyingPress | Cache Plugin | $3.5/mo (renewal price) |
Perfmatters | Miscellaneous optimizations | $24.95/yr |
GeneratePress | Theme | $249 (one-time) |
GenerateBlocks | Block Templates | $39/yr |
Google Workspace | Email Hosting | $6/mo |
Total Yearly Price | – | $477.95/yr (plus $249 one-time fee for GeneratePress) |
A cheaper shared hosting setup (without the cost of GeneratePress/GenerateBlocks):
Service | Category | Price |
---|---|---|
NameHero Turbo Cloud | Hosting | $7.98/mo for 3 years ($19.95/mo renewals) |
QUIC.cloud (Paid Plan) | CDN | $.01-.04/GB |
LiteSpeed Cache | Cache Plugin | Free |
Perfmatters | Misc optimizations | $24.95/yr |
NameHero | Email Hosting | Free on NameHero |
Total Yearly Price | – | $120.71 (plus $.01-.04/GB for QUIC.cloud) |
I hope you learned something new! Drop me a comment with any questions/suggestions.
If you want to support me, I use affiliate links in these reviews:
- Rocket.net review
- Cloudways review
- NameHero review
- FlyingPress settings
- Perfmatters settings
- GeneratePress review
Cheers,
Tom