Blog · Guides

Measuring WordPress Performance Without Fooling Yourself

Every WordPress optimization guide ends with a promise: do this, and your site gets faster. The part nobody checks carefully enough is the measurement itself. If you run PageSpeed Insights once before a change and once after, on different days, from different networks, with your caches in different states, the number you get back is closer to noise than signal. Here is how to test performance in a way that actually tells you something.

Lab Data and Field Data Are Different Instruments

PageSpeed Insights and Lighthouse produce lab data: a single simulated page load, on a fixed device profile, from a fixed location, at the moment you ran the test. It is reproducible and useful for debugging, but it is not what your visitors experience. It cannot see your actual traffic mix of phones, laptops, and networks.

Field data (the Core Web Vitals numbers pulled from the Chrome User Experience Report, shown in the same PageSpeed Insights report under a separate section) is aggregated from real visitors over the past 28 days. It is noisier and slower to reflect changes, but it is the truth about what people actually saw.

The rule: use lab data to diagnose and iterate quickly. Use field data to confirm that a change actually mattered to real users. Never quote a single lab run as proof that a fix worked. If you only have lab access, run the test multiple times (five is a reasonable minimum) and look at the median, not the best result.

Cold Cache, Warm Cache: Know Which One You Tested

A WordPress stack with LiteSpeed Cache, Redis or Memcached, and Cloudflare in front of it has at least three caching layers, and each one changes your numbers dramatically depending on whether it is warm.

  • Full-page cache (LiteSpeed Cache): the first visitor after a cache purge triggers a full PHP render. Every visitor after that gets a static HTML response until the cache expires or is purged again.
  • Object cache (Redis/Memcached): speeds up database-heavy operations even on cache misses, but only helps once the cache has been populated with real query results.
  • Edge cache (Cloudflare): caches static assets, and depending on your page rules, HTML too, at a data center near the visitor. A cold edge cache means the request travels all the way back to your origin server.

If you test immediately after clearing all caches, you are measuring your worst case: a full round trip through PHP, the database, and back to origin. If you test after the page has been hit a few times, you are measuring your best case. Neither one alone is “the truth,” but reporting them as if they were the same number is the most common mistake in performance write-ups.

Be explicit about which state you are testing. A clean before/after comparison looks like this:

# Purge everything, then let the page load once to warm it
wp cache flush
wp litespeed-purge all
curl -s -o /dev/null -w "%{time_total}\n" https://example.com/

# Now test warm, after the cache has been populated
curl -s -o /dev/null -w "%{time_total}\n" https://example.com/

Run both a cold and a warm test before your change, and both a cold and a warm test after. That gives you four numbers instead of one, and it tells you whether your optimization actually improved the origin render, the caching layer, or both.

Where You Test From Changes What You See

Cloudflare’s edge network and your origin server’s location both matter. A visitor in the same region as your origin, behind a nearby Cloudflare data center, will see very different latency than a visitor on the other side of the world. If your test tool runs from a single fixed location, and your actual audience is elsewhere, your lab numbers will be optimistic or pessimistic in a way that has nothing to do with your WordPress configuration.

When it matters, test from more than one location, or at least document which location you tested from so you are not comparing apples to oranges across different reports. Field data sidesteps this problem because it reflects wherever your real visitors actually are, which is one more reason to treat it as the final word.

Filter Out the Bots

Server logs and even some analytics tools will happily count crawler traffic, uptime monitors, and security scanners as “visitors.” These requests often skip your cache entirely (many bots send headers that request fresh content) and can make your average response time look worse than what real humans experience, or in some cases artificially better if a bot is just hitting a cached homepage repeatedly.

Before you trust a load-time metric pulled from raw logs, check whether it is filtered to real browser traffic. If you are using Cloudflare, its analytics dashboard separates bot traffic from human traffic, which is a cleaner source than raw server logs for this purpose. If you are relying on field data from Core Web Vitals, that data is already sourced from real Chrome users, so bot contamination is not a concern there.

A Repeatable Before/After Protocol

Here is a routine that removes most of the guesswork:

  1. Pick one change at a time. Testing a new PHP version and a new caching plugin in the same pass tells you nothing about which one helped.
  2. Record the state of every cache layer (LiteSpeed Cache, object cache, Cloudflare) before you start.
  3. Run a cold test and a warm test, at least three times each, and use the median.
  4. Wait for field data to update (give it a few days to a couple of weeks) before declaring victory based on real-world Core Web Vitals.
  5. Keep the raw numbers, not just a summary. “Faster” is not a measurement.

Reading the Numbers Against Real Thresholds

Once you have clean data, compare it against the thresholds that actually matter: Largest Contentful Paint (LCP) at or under 2.5 seconds, Interaction to Next Paint (INP) at or under 200 milliseconds, and Cumulative Layout Shift (CLS) at or under 0.1. These are the pass marks Google uses for Core Web Vitals, and they apply to field data, the real-user numbers, not a single lab run. A great lab score with poor field data usually means your test conditions do not match your real audience: different device, different network, or a cache state your visitors never actually see.

A managed stack running PHP 8.3 with OPcache, LiteSpeed with full-page caching, and Redis for object caching (which is the kind of layering a host like ServerBorn configures by default) removes a lot of the cold-start penalty, but it does not remove the need to measure honestly. Good infrastructure narrows the gap between your worst case and best case; it does not make the distinction between lab and field, or cold and warm, disappear.

Takeaway: a performance number is only as trustworthy as the conditions that produced it. Know whether you tested lab or field, cold or warm, from where, and with bots filtered out. Change one thing at a time, keep the raw numbers, and let the Core Web Vitals thresholds, measured in the field, be the number you actually report.