Speed & Core Web Vitals
Core Web Vitals, actually fixed
Most speed work is a caching plugin, a minification toggle and a screenshot of a better lab score. The field data does not move, because the causes were never addressed. We diagnose from real-user data, fix the causes, and hold the result to a budget — the same one our own site meets at a 1.4s average LCP and Lighthouse ≥ 95.
- Our own average LCP
- 1.4s
- Lighthouse, mobile
- ≥ 95
- Application JS we ship
- ~20 KB gzip
- Diagnosed from
- Field data, not lab scores
The problem
A caching plugin is not a fix
Caching solves one problem — regenerating the same page repeatedly — and leaves every other cause untouched. It does nothing about a hero image loading after the fonts, a third-party tag blocking the main thread for 400ms, or a cookie banner that pushes the whole layout down 300ms after paint.
The second trap is optimising the lab score. Lighthouse runs one simulated load on one simulated device. Google uses field data from real Chrome users, collected over a rolling 28-day window. A site can score 98 in the lab and still fail in the field, and the field is the one that counts.
What usually turns out to be the cause
- An unoptimised hero image, or the LCP element lazy-loaded by mistake
- Render-blocking CSS and fonts queued ahead of the content
- Third-party tags — chat widgets, heat maps, ad pixels — loaded eagerly
- Hydration or page-builder JavaScript creating long tasks on interaction
- Images, iframes and ads with no reserved space, so everything shifts
- Slow server response, usually a host or an uncached database query
For reference
The numbers we work to
Two different bars. Google’s thresholds are the pass mark; the budget is what we hold our own builds to, enforced in CI so a pull request that breaks it does not merge.
| Metric | Google’s “good” threshold | The budget we build to |
|---|---|---|
| LCP — Largest Contentful Paint | 2.5s or faster, at the 75th percentile | Under 1.8s on mobile 4G. Our own site averages 1.4s |
| INP — Interaction to Next Paint | 200ms or faster, at the 75th percentile | Under 150ms. Replaced FID as a Core Web Vital in March 2024 |
| CLS — Cumulative Layout Shift | 0.1 or less, at the 75th percentile | Under 0.05, which in practice means nothing visibly moves |
| TTFB — Time to First Byte | 800ms or faster is Google’s guidance | Treated as an input to LCP; if it is the cause we say so plainly |
| JavaScript shipped | Not a Core Web Vital | We keep our own application code near 20 KB gzip; the React framework itself adds about 160 KB on top. Shipping less of your own JavaScript is the largest lever you control on INP |
| Lighthouse performance, mobile | Lab signal only, not used by Google for ranking | 95 or above, used as a regression alarm rather than a goal |
What is included
What the engagement produces
Diagnosis
- Field data read first — CrUX and your own real-user monitoring if you have it
- Lab traces on throttled mobile to find the cause behind each field number
- A waterfall review identifying what blocks the LCP element specifically
- Long-task and main-thread profiling for INP, per interaction
- A third-party audit: what each tag costs in bytes and blocking time
The fixes themselves
- Image pipeline: correct formats, correct dimensions, correct priority hints
- Critical CSS inlined, the rest deferred; unused rules removed
- Font strategy — subset, preloaded, with metric-adjusted fallbacks to stop shift
- JavaScript reduced, split and deferred; long tasks broken up
- Explicit dimensions on every image, embed and ad slot
- Server and cache configuration where TTFB is the real constraint
Keeping it fixed
- A written performance budget per template
- Lighthouse CI wired into your pipeline, failing builds that regress
- Real-user monitoring configured so you see field data continuously
- A short guide for your team on what reliably breaks performance
- Re-measurement after the 28-day field window has refreshed
Metric by metric
What each number is really telling you
LCP — how long until the main thing appears
LCP measures when the largest element in the viewport finishes rendering. It is usually a hero image, a heading, or a background. The fix depends entirely on which, and on what is in front of it in the queue.
- Identify the actual LCP element before changing anything — it is often not what you assume
- Never lazy-load it; mark it fetchpriority="high" instead
- Serve it in a modern format at the size it is displayed, with explicit dimensions
- Preconnect to the origin it comes from if it is on another domain
- Get render-blocking CSS and synchronous scripts out of its way
- If TTFB is already most of the budget, the fix is server-side, not front-end
INP — how fast the page answers a tap
INP replaced First Input Delay as a Core Web Vital in March 2024, and it is stricter: it looks at the latency of interactions throughout the visit, not just the first one. It is overwhelmingly a JavaScript problem.
- Reduce the amount of JavaScript before optimising the JavaScript you keep
- Break long tasks up and yield to the main thread between chunks
- Audit third-party tags; a chat widget or a session recorder is often the single worst offender
- Defer hydration of components below the fold
- Make sure visual feedback paints before heavy work starts
CLS — how much the page moves under the reader
Layout shift is the most annoying of the three and usually the cheapest to fix. Almost all of it comes from content arriving without reserved space.
- width and height attributes, or an aspect-ratio, on every image, iframe and video
- Reserve space for ad slots and embeds before they load
- Load consent banners and promotional bars as overlays, not as inserted content
- Use size-adjusted fallback fonts so the swap does not reflow the text
- Avoid injecting content above existing content after paint
Field data versus lab data
This distinction causes more wasted money than any other in performance work. Lab tools simulate one load on one device; field data records what real visitors experienced. Google assesses Core Web Vitals on field data at the 75th percentile over 28 days — so a quarter of your visitors can still have a bad time while you pass.
- Use lab tools to diagnose causes, field data to decide whether you have a problem
- Expect roughly a month before a real fix is fully reflected in the field window
- CrUX only reports pages with enough traffic; low-traffic sites need their own monitoring
- A lab score of 98 and a failing field assessment is a common, legitimate combination
What caching can and cannot do
Caching plugins are not useless; they are just not a performance strategy. They help TTFB on repeated requests and can bundle assets. They cannot make an oversized hero image smaller, remove a blocking third-party script, or reserve space for a banner.
- Page caching improves TTFB, which improves LCP indirectly
- Aggressive minification and combination can make things worse on HTTP/2 and later
- Caching has no effect on INP, which happens after the page is already there
- Caching has no effect on CLS, which is a layout problem
- If a plugin's 'optimise' toggle fixed it, you did not have a hard problem
Our process
Diagnose first, then fix
Understand needs
Measure the real thing
Field data for the templates that matter, not one lab run of the homepage. Most sites have one slow template doing most of the damage, and it is rarely the one people test.
You getBaseline per template, field and lab
Strategize
Rank fixes by effect per hour
A costed list in order of impact. Often two changes account for most of the gain, and the rest is not worth your money — we will tell you where that line is.
You getPrioritised, costed remediation plan
Create & build
Implement and verify each change
Changes land on staging and are verified individually, so we know which one did the work. Nothing ships as an undifferentiated bundle of twenty tweaks.
You getImplemented fixes with per-change evidence
Optimize & grow
Guard it in CI
Speed regresses the moment someone adds a tag. A budget enforced in the build pipeline is what stops you paying for this twice.
You getCI budget, RUM dashboard, 28-day re-measurement
Honest scoping
When this is worth paying for
A good fit if
- Your site is structurally sound and specifically slow
- Search Console reports URLs failing Core Web Vitals
- You run paid traffic, where load time directly affects cost per acquisition
- Mobile is most of your traffic and most of your bounce
- You have a dev team who can maintain the result once we hand it over
Not the right fit if
- You want a score for a report. We optimise the experience; the score follows, and chasing the number alone is a waste of your money
- The site is a page-builder build on forty plugins — triage will cost more than a rebuild and leave the same foundation
- Your host is the bottleneck and moving is off the table; there is a floor we cannot get under
- The real problem is that the pages do not convert, which speed will not solve
One more thing. After the diagnosis we will tell you plainly if optimisation is not the right spend. A one-page findings document is useful to you either way.
Selected work
Projects that used Speed Optimization
Questions
Before you ask us
The things people ask about Speed Optimization before they get in touch. If yours is not here, ask directly — you will get a straight answer rather than a brochure.
Ask a questionWill optimisation break my site?
Everything is done on staging and verified change by change before it goes near production, so if something does break we know exactly which change caused it. Aggressive asset combination and script deferral are the risky operations and we test those individually rather than flipping them all at once.
Do I have to leave WordPress to be fast?
No. WordPress sites can hit these numbers. What usually has to go is the page builder, the plugin that loads its assets on every page for one feature, and the theme that ships a megabyte of CSS. If those are structural to how the site was built, a rebuild may be cheaper than the triage, and we will say so after the diagnosis rather than halfway through.
How much faster will my site get?
We will not put a number on it before the diagnosis, because the honest answer depends entirely on what we find. After the measurement step you get specific projected changes per fix, with the reasoning. A site bottlenecked on a slow host has a floor that front-end work cannot get under, and you would know that before committing.
Why did my PageSpeed score go back down?
Almost always because something was added — a new tag, a plugin, an embedded video, a marketing script someone pasted into the header. Performance is a state you maintain, not a project you finish. That is what the CI budget and real-user monitoring are for.
How long until Google notices the improvement?
Core Web Vitals are assessed on a rolling 28-day window of real-user data, so a fix shipped today is fully reflected roughly a month later. Lab scores change immediately, which is why reporting against them is tempting and misleading.
Does site speed actually affect rankings?
Core Web Vitals are a confirmed, if modest, ranking signal — they rarely outweigh relevance. The stronger argument is commercial: slow pages lose visitors before they see anything, and that shows up in bounce rate, conversion rate and paid-traffic costs well before it shows up in rankings.
Send us the URL that is letting you down
We will read your field data, run the traces and come back with what is actually causing it — including the case where the answer is that you do not have a problem worth paying to fix.