Skip to content
WP speed & Core Web Vitals

WordPress Speed Optimization: The 12 Fixes That Move LCP Most

Ranked from 250+ audits: the 12 WordPress speed optimization fixes that actually move LCP, with measured before and after, implementation time, and our plugin.

By WitsCode10 min read
WP speed & Core Web Vitals

If you only have two hours to spend on WordPress speed this quarter, the three fixes that move Largest Contentful Paint most are these. Compress and properly size the hero image that the browser is painting as your LCP element, which we see drop LCP by 0.8 to 1.6 seconds on roughly four out of five sites we audit. Eliminate render-blocking JavaScript on the critical path, which typically returns 0.4 to 0.9 seconds. Move to a host with a TTFB under 200 milliseconds and turn on full-page caching, which buys another 0.3 to 1.1 seconds and stabilises every other metric you care about. Everything else in this article is real, but those three are where the meaningful needle lives.

We have run this list against more than 250 audits over the last few years. The pattern is monotonous in a useful way. Sites that rank poorly on Core Web Vitals almost always fail in the same handful of places, and the long tail of clever-sounding tweaks people get sold on the internet rarely shows up in the data. What follows is the full ranked list of twelve fixes, grouped by the system they touch, with a measured before-and-after range from our engagements, the time we typically budget, and the plugin we reach for. Read it linearly if you are new to performance work. Skim the headings if you already know what you are looking for.

Image pipeline, where most LCP wins actually live

The single most consequential fix on a WordPress site is almost never glamorous. It is compressing and resizing the hero image. The LCP element on the average WordPress homepage is a hero photograph or banner, and the average WordPress site serves that hero at the original camera resolution because the page builder uploaded what the marketing person dragged in. We routinely see hero images shipped at 3200 pixels wide and 1.8 megabytes when the rendered slot is 1440 pixels and could comfortably live under 180 kilobytes. Fixing this single asset, properly resized to the maximum rendered width and compressed at quality 78 to 82, drops LCP from around 2.4 seconds to about 1.1 seconds on hero-heavy templates. We budget thirty to forty-five minutes per template the first time and use ShortPixel for the bulk job, occasionally Imagify on sites where the team already has a license. The reason we default to ShortPixel is the combination of WebP and AVIF delivery with adaptive sizing in one toggle, which leads neatly into the next fix.

Serving next-generation image formats is the second fix, and it stacks on top of the first rather than replacing it. Once images are compressed and resized, switching delivery to WebP or AVIF takes another twenty minutes of toggling settings and verifying the rewrite rule lands in the .htaccess file or the CDN edge. The honest before-and-after is that a hero that compressed to 200 kilobytes in JPEG often arrives in 35 to 90 kilobytes as AVIF, which is the difference between an LCP that scrapes under 2.5 seconds and one that comfortably sits under 1.8 on mid-tier mobile. ShortPixel handles both the conversion and the conditional delivery for browsers that support each format, which is the boring practical reason we use it rather than a more theoretically pure solution.

The third image-pipeline fix, and the one most often done wrong, is lazy loading. The native browser attribute makes lazy loading almost free to implement, and most caching plugins now apply it automatically below the fold. The mistake we see in roughly half of audits is that the LCP image itself ends up lazy-loaded, which delays the very thing the browser is measuring. The fix is fifteen minutes. Verify in DevTools that your hero element has loading="eager" and fetchpriority="high" applied, and that everything below the first viewport is loading="lazy". WP Rocket and Perfmatters both expose toggles for excluding the LCP image from lazy loading. Get this right and the bandwidth used during initial paint drops by forty to seventy percent, which on slow mobile connections is the difference between fast and broken.

JavaScript budget, which is where Total Blocking Time hides

The fourth fix, and the one that takes the most patience, is auditing and deferring JavaScript. The average WordPress site we inherit is running between fourteen and twenty-two active plugins, of which three or four are abandoned, two are duplicates of functionality the theme already provides, and several inject scripts on every page even when their feature only fires on one. We budget sixty to ninety minutes for a proper plugin audit and defer pass. Plugin Detective helps surface what is actually loading where. WP Rocket's Delay JavaScript Execution feature, applied carefully with exclusions for anything that paints above the fold, is what we use to push non-critical scripts past the LCP event. The typical Total Blocking Time improvement is from around 480 milliseconds to under 140, which on a slow phone is felt as the page becoming usable a full half-second earlier.

The fifth fix is closely related but worth separating, because it requires more taste. Page builders, especially the older builds of Elementor and the generic Visual Composer, ship their entire JavaScript and CSS bundle on every page even when the page in question uses none of those widgets. The remedy is conditional asset loading. We use Asset CleanUp Pro on smaller sites and Perfmatters Script Manager on larger ones to disable specific scripts on specific URLs. A non-builder page that was carrying 1.2 megabytes of JavaScript will routinely drop to 380 kilobytes after a careful pass. We budget thirty to forty-five minutes and always re-test the page after, because this is the fix that breaks things if you are careless about which scripts the contact form or the booking widget genuinely needs.

The sixth fix is third-party scripts, which is a category that creeps. Every chat widget, tag manager, heatmap tool, and review-aggregator badge added by a marketing team adds main-thread time, and they almost always run on every page rather than only the ones where they earn their keep. Removing or delaying a single chat widget routinely cuts about 280 milliseconds off LCP. Self-hosting Google Analytics through CAOS removes a DNS lookup and a render-blocker on slow connections. Perfmatters has per-page disable controls for the common offenders. We budget twenty to thirty minutes for this pass and treat it as a standing item to revisit every quarter, because marketing tools accumulate the way kitchen drawers accumulate takeout menus.

CSS budget, which controls First Contentful Paint

The seventh fix is critical CSS. The browser cannot paint until it has the styles for the above-the-fold content, and a WordPress site with no critical CSS strategy is usually waiting on a stylesheet of 200 to 400 kilobytes before showing anything. The fix is to inline the styles needed for the first viewport and load the rest asynchronously. WP Rocket generates and inlines critical CSS automatically and gets it right perhaps eighty percent of the time. Autoptimize paired with the CriticalCSS.com service is a more controllable alternative if you have time to QA. The honest measured before-and-after is First Contentful Paint dropping from around 1.8 seconds to 0.9 on the same page, same connection, with no other changes. Plugin-handled critical CSS takes about fifteen minutes to enable. Hand-written critical CSS for a custom theme is a two-to-three-hour exercise, which is occasionally worth it on the homepage and rarely worth it elsewhere.

The eighth fix is unused CSS removal, which is the more aggressive cousin of critical CSS. WordPress themes ship styles for every component the theme might ever render, and most templates use a small subset. WP Rocket and Perfmatters both offer Remove Unused CSS features that scan each URL and ship only what that page actually references. We have seen rendered CSS drop from 280 kilobytes to under 60 in this pass. The catch, and the reason we always budget thirty minutes for QA after enabling it, is that styles applied dynamically by JavaScript, hover states the scanner does not detect, and conditional sections behind tabs occasionally get pruned and produce visible regressions. Test every template type and every breakpoint before declaring the fix done.

Server and cache, which set the floor every other fix builds on

The ninth fix is the one nobody wants to hear if they signed up for two-dollar-a-month shared hosting. If your TTFB at the origin is above six hundred milliseconds, no amount of front-end optimisation will get your LCP below 2.5 seconds reliably, because TTFB alone is eating most of your budget. The fix is to migrate to a host where TTFB consistently lands under two hundred milliseconds. Our usual recommendations are Kinsta, Cloudways on Vultr High Frequency, or Rocket.net, depending on traffic and budget. The migration is a half-day exercise if the site is straightforward. The measured before-and-after we see most often is TTFB dropping from around 720 milliseconds to 180, which propagates into every other timing metric on the page.

The tenth fix is full-page caching plus an object cache, and on a properly configured host these are essentially free wins that surprisingly many sites have left switched off. Full-page caching turns a dynamic WordPress request that was spending 800 milliseconds rendering PHP and querying MySQL into a static file served in 90 milliseconds. WP Rocket handles this for sites whose host does not. Redis object cache, configured through the Redis Object Cache plugin, accelerates the dynamic parts that cannot be page-cached, which matters for logged-in users and WooCommerce checkouts. Twenty minutes of work if your host supports it, and the cached-page TTFB improvement is genuinely dramatic.

The eleventh fix is putting a CDN in front of the origin, which mostly matters if your audience is geographically distributed. A Bangalore-hosted site serving customers in London is paying for a transatlantic round-trip on every uncached asset. Cloudflare with the Automatic Platform Optimization add-on handles this elegantly for WordPress and improves international LCP by between 0.6 and 1.4 seconds in our measurements. BunnyCDN is the cheaper alternative we recommend when Cloudflare is overkill. About thirty minutes of configuration if DNS is already at Cloudflare, longer if it is not.

Font loading, the small fix with surprising leverage

The twelfth and final fix is fonts. WordPress sites still pull Google Fonts from the Google CDN by default, which adds a DNS lookup, a connection, and a render-blocking stylesheet to every page load, plus a privacy headache in the EU that is its own conversation. Self-hosting fonts and preloading only the specific weights that appear above the fold removes the third-party hop and prevents the flash of invisible text that drives Cumulative Layout Shift up. OMGF, properly named Host Google Fonts Locally, automates this in about thirty minutes. We see roughly 280 milliseconds of FOIT and CLS reduction from this fix alone, which is more than the size of the change suggests because it lands directly on the critical path. The font-display swap value, paired with a preload tag for the LCP heading weight and a font-family fallback that approximates the metrics of the brand font, is what produces the visibly stable first paint. Plugins will not get this last bit right for you on a custom theme, so we usually hand-write the four lines of head markup and call the job done.

What this list does not include, and a small admission

We left out some popular advice on purpose. Database cleaners rarely move user-perceived metrics on a properly cached site, and the ones that do you only need to run quarterly. Heartbeat tweaks belong in the server-cost bucket, not the speed bucket. Disabling Gutenberg block library CSS on sites that use Gutenberg blocks is a measurable but small win and we usually defer it to the second pass. Pre-fetching links on hover, swapping jQuery for vanilla JS, and switching from PHP 7.4 to 8.2 all show up on long checklists and all matter at the margins, but none of them touch LCP the way the twelve fixes above do, and the time to implement them is often disproportionate to the gain on an SMB site that is fighting to clear 2.5 seconds in the first place.

The honest admission is that the before-and-after ranges in this article are measured from our audits, not from a controlled lab. Your starting point is yours, and on a few sites we have seen the image pipeline produce only modest gains because the bottleneck was somewhere uglier in custom theme code, occasionally a render-blocking analytics script we did not flag in the first sweep, occasionally a theme that hard-codes its hero in CSS rather than HTML and changes which element the browser thinks is the LCP candidate. The ranking holds in aggregate. It will not hold for every individual site, which is partly why we still run an audit before quoting a remediation engagement, and partly why we are skeptical of any agency that promises a fixed price to fix Core Web Vitals before they have looked at the waterfall.

If you want us to run that audit on yours, we offer a fixed-scope WordPress performance audit that returns a prioritised remediation plan with the measured numbers in this article applied to your actual templates. It takes about a week of calendar time and roughly six hours of our engineering time. The output is the list of which of these twelve fixes will move your LCP most on your specific site, in what order to do them, what each one will cost in time, and what we would charge to implement them ourselves if you would rather not spend an evening with WP Rocket and DevTools. The audit price is credited against the remediation engagement if you choose to hire us for the work afterward, which is the model that has produced the most honest conversations with prospective clients. Get in touch through the WitsCode contact page and we will book you in for the next available audit slot.

Get weekly field notes.

Practical writing on shipping products, straight to your inbox. No spam.

Need help with this?

WordPress Development

We design and build web apps, MVPs, and SaaS products. Talk to us about what you are working on.

Talk to us

Want to discuss wp speed & core web vitals for your business?

Start a project and we'll talk through where you are, what's working, and the highest-leverage moves for the next 90 days.