Today’s goal
Treat performance as a user-experience property and an engineering discipline.
We will connect:
- field data, lab data, and representative measurement;
- LCP, INP, and CLS;
- network, JavaScript, rendering, memory, and layout cost;
- images, fonts, lists, workers, caching, and third parties;
- rendering topology and route-transition performance;
- DevTools traces, User Timing, PerformanceObserver, and RUM;
- budgets, regression detection, ownership, and performance culture.
By the end of today you can
- explain what Core Web Vitals measure and what they do not;
- use p75 and segmentation instead of hiding slow users in averages;
- diagnose LCP resource discovery and server delay;
- trace INP through input, main-thread work, rendering, and paint;
- prevent CLS through reserved space and stable layout;
- identify request waterfalls and unnecessary JavaScript;
- optimize large lists and CPU work only when evidence supports it;
- use browser tools and production signals together;
- define route and user-journey budgets;
- turn an optimization into a hypothesis, measurement, and regression guardrail.
The central principle
Performance work begins with a measured user problem, forms a hypothesis about its cause, and ends with a verified improvement under representative conditions.
An optimization is not successful because it sounds sophisticated.
It is successful when a user journey improves without unacceptable trade-offs.
Largest Contentful Paint
LCP measures when the largest relevant content element becomes visible in the viewport.
It can be:
- an image;
- a text block;
- a poster or background-like visual;
- another large content element selected by the browser.
The metric is about the critical content experience, not only one file.
Reduce unnecessary JavaScript
Possible strategies:
- remove unused dependencies;
- delay noncritical features;
- keep static content server-rendered;
- use route and component boundaries;
- avoid shipping server-only logic;
- replace a library with a platform capability when appropriate.
Measure the user journey after each change.
User Timing API
performance.mark("catalogue-start");
await loadCatalogue();
performance.mark("catalogue-ready");
performance.measure("catalogue-load", "catalogue-start", "catalogue-ready");Custom marks connect browser traces to product journeys.
Name them consistently and avoid collecting sensitive data.
Optimization should match cause
slow server → cache, data path, server work
late image → discovery, priority, dimensions
slow input → main-thread or render scope
layout jump → reserved geometry and font policy
large route → imports, splitting, dependency reviewAvoid applying a favorite optimization to every symptom.
Practical lab: Measure and Improve a Slow Interface
Diagnose a slow catalogue using field-like and lab measurements, then test whether virtualization, scheduling, asset changes, or caching address the measured cause.
Every change must begin with a hypothesis and end with a representative re-measurement.
Practical stages 19–24: production discipline
- Investigate memory.
- Create performance budgets.
- Add a CI guardrail.
- Build a RUM design.
- Build a performance regression report.
- Draw the final performance architecture.
Verification: the optimization improves a user journey or validated signal; no universal “zero INP” promise is made.
Troubleshooting guide (Part 1)
| Symptom | Likely cause |
|---|---|
| Lighthouse is good but users are slow | Lab conditions or route differ from field data |
| LCP image is compressed but still late | Discovery, TTFB, priority, or render delay |
| Click handler is short but INP is poor | Input delay or expensive rendering follows |
| CLS occurs after font load | Metrics and fallback geometry differ |
| Virtualization improves speed but breaks keyboard use | UX and accessibility contract was not tested |
Troubleshooting guide (Part 2)
| Symptom | Likely cause |
|---|---|
| Worker adds no benefit | Transfer and setup cost exceed CPU savings |
| Bundle shrinks but interaction is unchanged | Execution, rendering, or network is the actual bottleneck |
| Cache hit rate rises but data is wrong | Freshness, identity, or invalidation policy is weak |
| Budget fails randomly | Sample, environment, or threshold is not controlled |
Completion checklist
- field and lab data are used for different questions;
- p75 and segments are considered;
- LCP is diagnosed by subparts;
- INP includes input, handler, rendering, and paint;
- CLS sources have reserved geometry;
- network and JavaScript waterfalls are inspected;
- list and worker optimizations are evidence-driven;
- memory, cache, and subscription lifecycles are bounded;
- route budgets and performance ownership are explicit;
- production verification follows lab experiments.
Misconceptions to leave behind (Part 1)
| Misconception | Better mental model |
|---|---|
| Performance means Lighthouse score | It is a measured user experience |
| Fast on my machine means fast | Device, network, and route segments differ |
| Average performance is enough | Percentiles reveal slow experiences |
| LCP is image download time | Discovery, server, download, and render all matter |
| Every above-fold image should be preloaded | Prioritize the actual critical resource |
| Lazy loading always helps | It can delay content the user needs now |
| INP is only handler duration | Input, processing, render, and paint form the interaction |
| Memoization always improves speed | Caches have cost and may not target the cause |
Misconceptions to leave behind (Part 2)
| Misconception | Better mental model |
|---|---|
| Virtualize every list | Virtualization has UX and accessibility trade-offs |
| Workers make code faster | They trade main-thread work for communication cost |
| Compression solves JavaScript bloat | Parsing and execution remain |
| More code splitting is always better | Chunks have request and coordination cost |
| Prefetch everything | Speculation consumes user and server resources |
| SSR guarantees good Web Vitals | Topology moves work; it does not remove it |
| Optimization is final polish | Performance is an architectural constraint |