Web Performance
Web performance is how fast a page shows its main content, how quickly it reacts when the user clicks or types, and how still it stays while it loads. It is measured in the browser, from the user's side: an API that answers in 150 ms can still sit behind a page whose main image appears after four seconds.
Google's Core Web Vitals name these three experiences and set thresholds for them: Largest Contentful Paint (LCP) for loading, Interaction to Next Paint (INP) for responsiveness and Cumulative Layout Shift (CLS) for visual stability. A "Pay" button that jumps down just as the user taps it is a visual stability problem, and CLS turns it into a number.
Why it matters
Users experience a slow or jumpy page as a broken one: they tap the wrong button when the layout moves, tap twice when nothing seems to happen, or leave. Functional tests rarely catch this, because on a fast office laptop the page eventually works.
Performance also regresses quietly: a heavier image, a new third-party script or a banner inserted at the top can slow a page down without failing a single test case. A tester who knows the metrics and thresholds turns "it feels slow" into a measured, reproducible defect.
The three Core Web Vitals and their thresholds
Each Core Web Vital measures one part of the experience, and web.dev defines three bands for each: good, needs improvement and poor.
- LCP (Largest Contentful Paint), loading: the time from the start of navigation until the largest image, text block or video in the viewport is rendered. Good: 2.5 s or less. Poor: above 4.0 s.
- INP (Interaction to Next Paint), responsiveness: the delay from a click, tap or key press to the next frame the browser paints; over the whole visit, the slowest interaction counts, ignoring rare outliers. Good: 200 ms or less. Poor: above 500 ms. INP replaced First Input Delay (FID) in 2024.
- CLS (Cumulative Layout Shift), visual stability: a score without a unit for content that moves unexpectedly, taken from the largest burst of layout shifts; shifts right after the user's own input are not counted. Good: 0.1 or less. Poor: above 0.25.
- Judging a page: each metric is read at the 75th percentile (p75) of visits, the value that 75% of visits stay at or below, separately for mobile and desktop, and the page passes only when all three are good. The limits are exact boundaries: an LCP of 2,500 ms is good, 2,501 ms is not.
- Example: at the 75th percentile, a product page with LCP 3.1 s, INP 180 ms and CLS 0.18 fails, because LCP and CLS need improvement although INP is good.
LCP: loading, in seconds
- ≤ 2.5 sGood
- 2.5–4.0 sNeeds improvement
- > 4.0 sPoor
- 13.1 s Example product page, p75Above 2.5 s: needs improvement.Caution
INP: responsiveness, in milliseconds
- ≤ 200 msGood
- 200–500 msNeeds improvement
- > 500 msPoor
- 1180 ms Example product page, p75At or below 200 ms: good.Pass
CLS: visual stability, score without a unit
- ≤ 0.1Good
- 0.1–0.25Needs improvement
- > 0.25Poor
- 10.18 Example product page, p75Above 0.1: needs improvement.Caution
Thresholds from web.dev, read separately for mobile and desktop; a page passes only when all three metrics are good.
Lab data and field data
Lab data is measured in a controlled environment: one device profile, one network setting, usually an empty cache. Two lab tools matter most: the DevTools Performance panel, and Lighthouse, the audit tool in Chrome DevTools that loads the page under simulated mobile or desktop conditions and reports the metrics and a score. Lab data is repeatable, available before release and shows the cause: the LCP element, the script that blocked the main thread, the element that moved.
Field data comes from real users on their own devices and networks, also called real user monitoring (RUM). The Chrome User Experience Report (CrUX) collects it for public pages with enough Chrome traffic and reports the 75th percentile over the previous 28 days; Google's PageSpeed Insights web page shows it for a URL next to a Lighthouse lab run, and teams can collect their own with the open-source web-vitals library. Field data shows what users actually get, but it arrives late, does not exist for staging and rarely explains the cause.
- INP needs real interactions, so a lab tool that only loads the page cannot report it. Lighthouse shows Total Blocking Time (TBT), the total time long tasks blocked the main thread while the page loaded, as a lab proxy: a high TBT warns that interactions may be slow, but it is not INP.
- Lab and field values for the same page usually differ: real users have other devices, warm caches and other screen sizes, and therefore other LCP elements, and they scroll and click.
- Use field data to decide whether a problem exists and how big it is; use lab data to find the cause, compare builds before release and confirm a fix. The Lighthouse score (0 to 100) is a lab summary, not the Core Web Vitals assessment.
Testing page speed step by step
Treat a performance check like any other test: chosen pages and interactions (search, product, checkout; filter, add to cart), fixed conditions, an expected result and evidence. Test mobile and desktop separately.
- Fix the conditions: an incognito window without extensions, a stated build and environment, Lighthouse's mobile setting or stated CPU and network throttling, and one load with an empty cache and one with a warm cache.
- Run Lighthouse several times and use the median (the middle value once the results are sorted), because results vary between runs. Record the metric values and the LCP element, not only the score.
- Record key interactions in the Performance panel with CPU throttling: long tasks on the main thread show what a slow click waits for, and the Layout shifts track shows which element moved. Images without dimensions, late banners and web fonts are common causes of layout shifts.
- In the Network panel, check the largest files, compression (
Content-Encoding), cache headers of static files and how long the HTML document takes, since server time is part of LCP. - Compare with a baseline: the previous build under the same conditions, or a budget the team agreed, such as LCP at most 2.5 s with the mobile setting. The difference is your finding.
Try it: Response Time Analyzer Try it: Response Size Analyzer Try it: Cache Header Analyzer
Worked example: a product page that fails its Core Web Vitals
PageSpeed Insights shows field data for a shop's product page on mobile: LCP 3.1 s, INP 180 ms, CLS 0.18. To find the causes, the tester runs Lighthouse five times on staging and records a Performance trace:
- Lab LCP (4.4 s) is worse than field LCP (3.1 s) because of the throttling and the empty cache; both point the same way, which is what matters.
- Finding 1: the 2.4 MB LCP image has
loading="lazy", so the browser requests it late. Evidence: the LCP element and the waterfall. - Finding 2: the promo banner is inserted above the price after the first render, with no space reserved, and pushes the content down. Evidence: the trace and a screen recording.
- INP is good in the field, so TBT alone does not justify a responsiveness defect; it is noted as a risk to recheck.
- After the fixes, confirmation testing repeats the same lab runs (LCP 2.2 s, CLS 0.02). Field values improve gradually, because CrUX covers the previous 28 days.
Product page /p/1042, staging, build 5.8.0
Lighthouse in DevTools, mobile, incognito, 5 runs, median
Metric Median Good up to Observation
LCP 4.4 s 2.5 s LCP element: hero image, 2.4 MB
TBT 620 ms - lab proxy for INP, no CWV threshold
CLS 0.21 0.1 shift when the promo banner appears
Network hero.jpg 2.4 MB loading="lazy" request starts at 1.9 s
Trace layout shift at 2.6 s: banner inserted above the priceCommon mistakes
- Testing only on a fast office laptop and network, and concluding the page is fast.
- Reporting one Lighthouse run, or only the score, instead of the median of several runs with metric values and conditions.
- Expecting lab and field numbers to match, or treating lab values as what users experience.
- Checking loading but ignoring responsiveness: a page can load quickly and still react slowly to every tap.
- Using outdated metrics such as FID, or thresholds from old articles, without checking web.dev.
- Filing "the page is slow" without the page, device setting, throttling, build and baseline, so nobody can reproduce it or verify the fix.
The QA perspective
On a real team, performance belongs in the acceptance criteria of user-facing pages. In refinement, ask which pages have a budget, for which device class, and whether field data comes from CrUX or the team's own monitoring. Performance is a non-functional requirement, one that states how well the page works rather than what it does, and a testable one names the metric, percentile, device class and limit.
Before release, compare the release candidate with the previous build under the same lab conditions; after release, review the field data with the developers. A performance defect report gives the metric and value, the conditions, the baseline or threshold, the element or script responsible and the evidence.
Practice exercise
Classify and report Core Web Vitals results
A search results page has the field and lab results below. Classify each field value, decide whether the page passes the Core Web Vitals assessment on mobile and on desktop, and explain why lab and field LCP differ.
Then write the summary and evidence of one defect report and name your next measurement. If you can, repeat the routine on a public page you are allowed to test.
Search results page /search
Field data (CrUX), 75th percentile
LCP INP CLS
Mobile 2.4 s 380 ms 0.05
Desktop 1.6 s 120 ms 0.02
Lighthouse in DevTools, /search?q=shoes, mobile, incognito, same staging build
Run 1 LCP 3.0 s TBT 900 ms CLS 0.04 Score 61
Run 2 LCP 2.7 s TBT 760 ms CLS 0.04 Score 68
Run 3 LCP 2.9 s TBT 820 ms CLS 0.05 Score 64- Classify the six field values.
- Decide pass or fail per device class.
- Take the median of each lab metric and compare lab and field LCP.
- Write the summary, the evidence and the next measurement.
Show the model answer
Mobile: LCP 2.4 s good, INP 380 ms needs improvement (above 200 ms, not above 500 ms), CLS 0.05 good, so the page fails on mobile. Desktop: all three good, so it passes.
Lab medians: LCP 2.9 s, TBT 820 ms, CLS 0.04. Lab LCP is higher because the mobile setting throttles CPU and network and starts with an empty cache, while many real users have faster phones or cached files.
The high TBT fits the slow field INP: the main thread is busy, so taps wait. Summary: "Search results, mobile: INP 380 ms at p75, good is 200 ms or less; lab TBT 820 ms". Evidence: the PageSpeed Insights field data, the three Lighthouse reports with build and settings, and a Performance trace.
Next measurement: record the page's real interactions, such as opening the filters or changing the sort order, in the Performance panel with CPU throttling, to find the long task behind the delay. The Lighthouse score itself is not the defect.
Frequently asked questions
Is the Lighthouse performance score a Core Web Vitals result?
No. The score from 0 to 100 is a weighted summary of lab metrics from one run under simulated conditions. The Core Web Vitals assessment uses field data at the 75th percentile and needs LCP, INP and CLS all to be good. Use the score to compare builds under equal conditions, not as the pass criterion.
Why does a page look fine in Lighthouse but fail in the field data?
They measure different things. Lighthouse loads the page once, in a lab, without real interactions, so it cannot measure INP and misses shifts that happen while users scroll. Field data covers 28 days of real visits on many devices. Trust the field data for the verdict and use the lab to investigate.
Can I test Core Web Vitals on a staging environment?
Yes, and you should measure lab values on staging to catch regressions before release. Staging has no CrUX field data because real users do not visit it; field values appear only after release, through CrUX or the team's own monitoring.
How is web performance different from load testing?
Web performance, as in this lesson, is what one user's browser experiences: loading, responding and staying stable. Load testing, covered in the performance testing module, measures how the server behaves when many users arrive at once. A page can have good Core Web Vitals with one user and still slow down under load when the server's response time grows.
References
- Web VitalsThe Core Web Vitals (LCP, INP, CLS): what they measure and the thresholds for a good user experience.
- What are browser developer tools? — MDNAn introduction to the developer tools built into browsers — the inspector, the JavaScript console and the debugger — for examining a page while testing it.
Practise with Mutqan tools
Measure an endpoint's response time over several samples: min, max, average, median and p95.
Analyze response size: raw vs compressed bytes, headers size, JSON structure weight and largest fields.
Analyze Cache-Control, Expires, ETag, Last-Modified, Vary and Age headers and explain how browsers and CDNs will cache the response.
Go deeper
Your progress on this topic
Not started
Mark the topic complete when you have studied it and done the exercise.
Sign in to track your progress
Mark topics complete, continue where you left off and unlock specialisation exams.