DEV Community

Cover image for I Got a WordPress Site to 972 ms — and I Won't Show You a Before/After
Joshua
Joshua

Posted on Originally published at hafenpixel.de

I Got a WordPress Site to 972 ms — and I Won't Show You a Before/After

Every WordPress performance post follows the same script: a red screenshot, a green screenshot, and a percentage in the headline.

I can't give you that one, and the reason is the most useful thing in this article.

A care service had a slow WordPress site on Divi. I reviewed it and fixed it in under two hours. The documented end state: 972 ms load time, 2.0 MB page size, 65 requests, Pingdom grade B87.

What I don't have is an archived baseline. The original numbers were never saved. So I'm not going to reverse-engineer a "73% faster!" headline out of memory — which, if you read enough of these posts, is exactly what a lot of them are doing.


Two problems, one of them invisible to tooling

Visitors experienced this as two separate annoyances. Pages built up slowly. And above the actual content sat a banner asking them to unblock external content — which looked like part of the site but was a consent misconfiguration.

That second one matters methodologically: a pure performance report would have scored it as irrelevant. It costs almost no milliseconds. It just ruins the page. You only catch it by opening the site like a human being after you've read the waterfall.


The actual causes

Nothing exotic. Pingdom and PageSpeed pointed at a short list:

  • No effective page cache. WordPress rebuilt pages from scratch on repeat visits.
  • Oversized PNGs. Images shipped far larger than their rendered size, barely compressed.
  • A misassigned Borlabs content blocker. It was attached to too broad a container, so the placeholder landed on regular page content instead of on an embedded third-party service.

Worth saying plainly: "Divi is slow" would have been a lazy diagnosis. Page builders do generate more CSS and markup than a hand-built theme. But the actual weight here was caching, images and one wrong selector. The theme was never touched.


What I did, in order

Order matters when the clock is running.

Caching first. WP Rocket, so WordPress can reuse finished page output instead of recomputing every visit. A page cache doesn't speed up any individual asset — it removes work from the critical start of the request.

Then the media. Images evaluated against their actual rendered size. An image displayed at 800 px wide has no business being several thousand pixels of lossless PNG. Right dimensions, right format for the subject, compression where the loss isn't visible in normal use.

Those two attack different parts of the problem: caching reduces server work and time-to-HTML, image work reduces what the browser then has to download and decode. They compound rather than overlap.

Then the consent blocker. Borlabs Cookie blocking external content until consent is correct behavior — when there's actually a consent-requiring service at that spot. Assigned too broadly, the placeholder covers normal content. I fixed the assignment. I did not switch consent management off to make a banner disappear, which would have been fast and professionally wrong. Afterwards I checked the page both with and without consent given.

Then verification. After every change: home page, navigation, forms, embedded content. Minification and deferred JavaScript will happily buy you a green score and a broken menu.


What I deliberately didn't do

This list is the actual craft.

  • Didn't swap the theme. A Divi replacement means retesting layout, content and responsive behavior. That is not a two-hour job.
  • Didn't bulk-disable plugins. Plugin count isn't the metric. Whether a plugin does unnecessary work on the request being measured is.
  • Didn't enable aggressive JS delay. Its side effects on navigation and forms couldn't be tested properly in the time available, so it stayed off.

Good performance work is usually a small number of causes fixed properly, plus a list of risky things you chose not to touch.


Reading the result honestly

Documented after
Performance grade B87
Page size 2.0 MB
Load time 972 ms
Requests 65
Effort under two hours

That 2.0 MB is worth staring at: the site is under one second and still shipping 65 requests and a meaningful payload for a simple page. "Fast" and "fully optimized" are not the same state. More was possible. It would have changed the ratio of effort, risk and measurable benefit.

Without an archived baseline, the honest claim is the documented end state after under two hours. Less spectacular than a fabricated percentage, considerably more credible.

If you take one operational habit from this post: archive the baseline before you touch anything. Not for the client — for yourself, so you can tell later which change actually did the work.


Optimize or rebuild?

Targeted optimization Rebuild
Makes sense when design and content still work, the tech slows things down structure, content or audience no longer fit
Typical levers caching, image formats, configuration errors information architecture, templates, content, tech
Effort hours to days weeks to months
Risk small and reversible rankings, redirects, editorial work
Outcome same site, measurably faster new site, new starting point

This project was clearly the left column: three bounded causes, none of them structural.


Key Takeaways

  1. Archive your baseline measurement. Without it you have no honest story, only a number.
  2. Open the site as a user. A consent placeholder over your content costs no milliseconds and ruins the page anyway.
  3. Caching and image sizing before micro-optimizations. Don't hunt milliseconds in a script while shipping megabytes of unnecessary image data.
  4. Never fix a consent problem by disabling consent management. Fix the assignment.
  5. A green metric with a broken menu is a failed optimization. Re-test function after every change.

Full technical write-up on hafenpixel.de. If you want the deeper end of WordPress work, here's an onOffice CRM integration three agencies couldn't finish.

Top comments (0)