<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>Coder Legion - Recent posts tagged lighthouse</title>
<link>https://coderlegion.com/tag/lighthouse</link>
<description>Powered by Question2Answer</description>
<item>
<title>When should you lazy load images (and when does it hurt LCP)?</title>
<link>https://coderlegion.com/31172/when-should-you-lazy-load-images-and-when-does-it-hurt-lcp</link>
<description>&lt;p&gt;A short rule list for loading=&quot;lazy&quot;: below the fold yes, LCP hero no, and retest after every theme or plugin change that touches images.&lt;/p&gt;
&lt;p&gt;A theme update or optimisation plugin turns on lazy loading for every image. Bandwidth on long articles looks better in the waterfall, yet PageSpeed Insights still names a deferred hero as Largest Contentful Paint, or lab LCP gets worse than last month. That outcome is common when &lt;code&gt;loading=&quot;lazy&quot;&lt;/code&gt; is treated as a global performance switch instead of a per-image choice.&lt;/p&gt;
&lt;p&gt;The full decision guide, including iframes, video, and lab-versus-field checks, lives on our blog in &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/lazy-loading-lcp-cls-loading-lazy-attribute?utm_source=hashnode&amp;amp;utm_medium=referral&amp;amp;utm_campaign=when-lazy-load-images-hurt-lcp&quot;&gt;Lazy Loading for LCP and CLS: When to Use loading=&quot;lazy&quot; (and When Not To)&lt;/a&gt;. Formats, sizing, and CDN work sit beside that in &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/image-optimisation-strategies-better-lcp-scores?utm_source=hashnode&amp;amp;utm_medium=referral&amp;amp;utm_campaign=when-lazy-load-images-hurt-lcp&quot;&gt;Image Optimisation Strategies for Better LCP Scores&lt;/a&gt;. What follows is the short checklist we use in reviews: when lazy loading images helps, when it hurts LCP, and which CMS habits to watch.&lt;/p&gt;
&lt;h3 id=&quot;three-checks-before-you-lazy-load-an-image&quot;&gt;Three checks before you lazy-load an image&lt;/h3&gt;
&lt;p&gt;These three questions usually decide whether &lt;code&gt;loading=&quot;lazy&quot;&lt;/code&gt; belongs on an &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Is it in the first viewport on phone and desktop?&lt;/strong&gt; If yes for either primary breakpoint, leave it eager.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Could PageSpeed Insights or Chrome name it as LCP?&lt;/strong&gt; If it is the hero, primary product shot, or large above-the-fold banner, omit lazy, or set &lt;code&gt;loading=&quot;eager&quot;&lt;/code&gt; when a plugin injects lazy by default.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Does the markup reserve space?&lt;/strong&gt; Width and height attributes or an aspect-ratio rule should be present before you defer the fetch, so Cumulative Layout Shift does not replace the LCP problem.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If the template or page builder does not make those answers obvious, identify the first-screen image before you change attributes. A plugin toggle is not a substitute for knowing which image paints first. Note the exclusions in the work item so the next theme update has a clear list.&lt;/p&gt;
&lt;h3 id=&quot;when-lazy-loading-images-helps-bandwidth-without-hurting-lcp&quot;&gt;When lazy loading images helps bandwidth without hurting LCP&lt;/h3&gt;
&lt;p&gt;Lazy loading images is usually right for content that starts offscreen: article body photos after the fold, related-product grids, footer logos, long category galleries, and comment avatars. Those bytes should not compete with the critical path on first paint. On a long post with many images, native lazy loading can cut early mobile bandwidth sharply without changing what the user sees first.&lt;/p&gt;
&lt;p&gt;Eager versus lazy works better as a short policy per template than as a single sitewide switch. Eager fits the LCP candidate and other first-screen images on common breakpoints. Lazy fits everything that needs scroll or a tab change before it matters. Check phone width as well as desktop: an image that looks “below the fold” on a large monitor can sit in the first screen on a phone, and that traffic often dominates field data.&lt;/p&gt;
&lt;h3 id=&quot;when-loading-lazy-hurts-largest-contentful-paint&quot;&gt;When &lt;code&gt;loading=&quot;lazy&quot;&lt;/code&gt; hurts Largest Contentful Paint&lt;/h3&gt;
&lt;p&gt;LCP marks when the largest above-the-fold content element becomes visible. If that element is an image marked &lt;code&gt;loading=&quot;lazy&quot;&lt;/code&gt;, the browser may delay the request even though the image is already on screen. Lab tools show that as higher resource load delay and a worse LCP. Google’s guidance and support threads still treat “do not lazy-load the LCP image” as a first triage step, not a rare edge case.&lt;/p&gt;
&lt;p&gt;The fix is usually small. Remove &lt;code&gt;loading=&quot;lazy&quot;&lt;/code&gt; from the named LCP image (and matching sources in &lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt;). &lt;code&gt;fetchpriority=&quot;high&quot;&lt;/code&gt; fits when the LCP URL is known early and other resources are not already marked high. Preloading and lazy-loading the same URL fights itself. A reasonably sized eager hero usually beats a huge lazy hero on LCP, even when a plugin dashboard calls the waterfall optimised.&lt;/p&gt;
&lt;h3 id=&quot;cms-and-theme-traps-that-lazy-load-the-hero&quot;&gt;CMS and theme traps that lazy-load the hero&lt;/h3&gt;
&lt;p&gt;WordPress themes, page builders, and Shopify settings often inject &lt;code&gt;loading=&quot;lazy&quot;&lt;/code&gt; on every attachment. Logos, banners, and first product images get deferred with the gallery. Elementor and similar stacks show up often in “lazy load LCP” threads for that reason. A CDN or image plugin that rewrites markup can put lazy back after the theme was fixed once.&lt;/p&gt;
&lt;p&gt;When scores drop after a “performance” plugin install, open the LCP element detail before you change hosting plans. Exclude the first-screen image from auto-lazy rules, or override with eager on that node. Record the exclusion in the monthly notes so the next theme update does not silently put lazy back on the hero.&lt;/p&gt;
&lt;h3 id=&quot;quick-verify-lab-lcp-element-after-a-lazy-loading-change&quot;&gt;Quick verify: lab LCP element after a lazy-loading change&lt;/h3&gt;
&lt;p&gt;After any change that touches image markup or lazy defaults, re-run PageSpeed Insights or your scheduled lab profile on the homepage and other priority pages. Check which element is LCP, whether that element is still lazy-loaded, and whether deferred below-the-fold images reserve space with width/height or aspect-ratio. One green Lighthouse run on a staging URL is not enough if production themes differ by template.&lt;/p&gt;
&lt;p&gt;Comparing the same lab profile before and after the change, kept in monitoring history, is how agencies catch a theme update that re-applies sitewide lazy loading three weeks later, when nobody remembers the original ticket. Scheduled runs on the homepage and other priority pages are more reliable than another one-off Insights paste after each deploy. That habit turns a one-time attribute fix into something the next quarterly review can still prove.&lt;/p&gt;
&lt;h3 id=&quot;faq&quot;&gt;FAQ&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Should every image use &lt;code&gt;loading=&quot;lazy&quot;&lt;/code&gt;?&lt;/strong&gt;&lt;br&gt;
No. Offscreen images are the usual fit. Keep the LCP candidate and other first-viewport images eager. Sitewide lazy loading is a common cause of worse lab LCP.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Does lazy loading fix Cumulative Layout Shift?&lt;/strong&gt;&lt;br&gt;
Not by itself. Reserve space with width and height or aspect-ratio CSS. Lazy loading without reserved space can make CLS worse when images appear late and push the layout.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Is the HTML &lt;code&gt;loading&lt;/code&gt; attribute enough, or do we still need a JavaScript library?&lt;/strong&gt;&lt;br&gt;
For ordinary images, native lazy loading is usually enough in modern browsers. Older themes still ship JavaScript lazy libraries; check whether those libraries also defer the hero. Knowing which mechanism is in use belongs in the work item before anyone blames hosting.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How do we know which image is LCP?&lt;/strong&gt;&lt;br&gt;
Use the LCP element detail in PageSpeed Insights or Lighthouse on phone and desktop widths. Do not guess from the design mockup alone.&lt;/p&gt;
&lt;h3 id=&quot;cta&quot;&gt;CTA&lt;/h3&gt;
&lt;p&gt;If lazy loading is already “on” everywhere, treat the toggle as incomplete until the LCP image is named. Below-the-fold images usually stay lazy; the hero stays eager; space is reserved; theme and plugin changes get a retest. For the longer guide with iframes, video, and lab-versus-field detail, use the Watcher lazy-loading post linked above. For formats and sizing that keep eager heroes small enough to ship, use the image optimisation piece. When you need scheduled lab history across many client pages so a theme update cannot silently defer the hero again, run continuous PageSpeed checks in &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/?utm_source=hashnode&amp;amp;utm_medium=referral&amp;amp;utm_campaign=when-lazy-load-images-hurt-lcp&quot;&gt;Apogee Watcher&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;references&quot;&gt;References&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/lazy-loading-lcp-cls-loading-lazy-attribute&quot;&gt;Lazy Loading for LCP and CLS: When to Use loading=&quot;lazy&quot; (and When Not To)&lt;/a&gt; (Apogee Watcher)&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/image-optimisation-strategies-better-lcp-scores&quot;&gt;Image Optimisation Strategies for Better LCP Scores&lt;/a&gt; (Apogee Watcher)&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://web.dev/articles/browser-level-image-lazy-loading&quot;&gt;Browser-level image lazy loading for the web&lt;/a&gt; (web.dev)&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://developer.mozilla.org/en-US/docs/Web/Performance/Guides/Lazy_loading&quot;&gt;Lazy loading&lt;/a&gt; (MDN Web Docs)&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://web.dev/blog/common-misconceptions-lcp&quot;&gt;Common misconceptions about Largest Contentful Paint&lt;/a&gt; (web.dev)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;Originally published on &lt;a rel=&quot;nofollow&quot; href=&quot;https://devlog.apogeewatcher.com/when-should-you-lazy-load-images-and-when-does-it-hurt-lcp&quot;&gt;Hashnode&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/31172/when-should-you-lazy-load-images-and-when-does-it-hurt-lcp</guid>
<pubDate>Thu, 15 Oct 2026 07:36:37 +0000</pubDate>
</item>
<item>
<title>Brotli compression is on: why is PageSpeed / LCP still slow?</title>
<link>https://coderlegion.com/30909/brotli-compression-is-on-why-is-pagespeed-lcp-still-slow</link>
<description>&lt;p&gt;A green compression toggle is not an LCP fix. Confirm Content-Encoding on the critical path, then check the LCP element and Time to First Byte that still dominate the lab run.&lt;/p&gt;
&lt;p&gt;The CDN panel shows Brotli enabled and the host checklist ticks compression, yet PageSpeed Insights on the homepage or checkout URL still shows a slow Largest Contentful Paint, or the Performance score barely moves after the change. Those two facts can both be true. Brotli compression shrinks text on the wire; it does not change the LCP element, a slow origin response, or a lab path that never negotiated &lt;code&gt;br&lt;/code&gt; on the files that matter.&lt;/p&gt;
&lt;p&gt;How to turn compression on without breaking scores is already covered on our blog in &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/brotli-gzip-compression-pagespeed?utm_source=hashnode&amp;amp;utm_medium=referral&amp;amp;utm_campaign=brotli-on-pagespeed-lcp-still-slow&quot;&gt;Brotli and Gzip Compression: Shrink Text Assets Without Breaking PageSpeed Scores&lt;/a&gt;. Caching and reuse sit beside that work in &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/cache-control-headers-for-web-performance-cdn-and-browser-caching-that-sticks?utm_source=hashnode&amp;amp;utm_medium=referral&amp;amp;utm_campaign=brotli-on-pagespeed-lcp-still-slow&quot;&gt;Cache-Control Headers for Web Performance&lt;/a&gt;. What follows here is the triage we run when the toggle is already green and the lab result is still poor: confirm encoding on the critical path, then address the bottlenecks compression was never going to fix.&lt;/p&gt;
&lt;h3 id=&quot;confirm-brotli-is-actually-on-the-critical-path&quot;&gt;Confirm Brotli is actually on the critical path&lt;/h3&gt;
&lt;p&gt;A dashboard labelled “Brotli” often means the edge &lt;em&gt;can&lt;/em&gt; compress. Lighthouse and PageSpeed Insights care whether the HTML document and the render-blocking CSS and JavaScript on that URL arrived with &lt;code&gt;Content-Encoding: br&lt;/code&gt; or &lt;code&gt;gzip&lt;/code&gt;. Those are different claims. Open the Network panel (or &lt;code&gt;curl -sI&lt;/code&gt; with &lt;code&gt;Accept-Encoding: br, gzip&lt;/code&gt;) on the document URL and on each large text resource in the critical path. Look for &lt;code&gt;content-encoding&lt;/code&gt; and for transfer size versus content size. If the document is compressed but the main stylesheet is not, the Enable text compression audit can still fail, and paint can still wait on uncompressed bytes.&lt;/p&gt;
&lt;p&gt;Partial coverage is the usual miss after a “we enabled Brotli” ticket. Origin middleware compresses HTML; the CDN serves fingerprinted CSS from a bucket that never negotiated Brotli; fonts and JSON follow yet another path. Agencies also see the reverse: the lab client hits a cache or region where encoding differs from the URL the engineer tested by hand. Until you can name the encoding on the document and the two or three largest text blockers, treat the toggle as incomplete evidence.&lt;/p&gt;
&lt;h3 id=&quot;why-brotli-can-leave-largest-contentful-paint-unchanged&quot;&gt;Why Brotli can leave Largest Contentful Paint unchanged&lt;/h3&gt;
&lt;p&gt;LCP measures when the largest visible element finishes rendering, not when every text file is as small as possible. Compression helps when download time for HTML, CSS, or critical JavaScript was a meaningful slice of that path. It does nothing useful for an LCP image that is still a multi-megabyte JPEG, lazy-loaded by mistake, or discovered late after client-side rendering. Decode and layout work on the main thread also sit outside what compression can fix: a smaller JavaScript transfer still costs the same parse and execute time once the bytes arrive.&lt;/p&gt;
&lt;p&gt;In our experience, teams over-credit the compression ticket because it is easy to mark done. The lab waterfall still shows a late LCP resource, a long Time to First Byte, or render-blocking scripts that compression only shortened by tens of milliseconds. When transfer size was never the bottleneck, expecting a Core Web Vitals step-change from Brotli alone is the wrong bet. Use the LCP element detail in PageSpeed Insights or Lighthouse: if the element is an image or a late text block waiting on fonts and scripts, compression is support work, not the fix.&lt;/p&gt;
&lt;h3 id=&quot;when-enabling-brotli-makes-pagespeed-insights-worse&quot;&gt;When enabling Brotli makes PageSpeed Insights worse&lt;/h3&gt;
&lt;p&gt;Compression can raise Time to First Byte (TTFB) when the origin or edge encodes HTML on every request at a high Brotli quality level. Smaller bodies help only after the first byte is available. If CPU queues behind dynamic compression, every paint metric starts later even though transfer size looks healthier in the waterfall. That pattern shows up after someone raised Brotli quality to the maximum on dynamic pages without precompressing static assets or without a moderate quality setting for HTML.&lt;/p&gt;
&lt;p&gt;Other regressions are quieter. Double compression (a gzip wrapper around an already-Brotli body, or filters stacked at origin and edge) burns CPU without shrinking useful bytes. Compressing JPEG, PNG, WebP, AVIF, or MP4 as if they were text adds work for almost no gain. Missing or wrong &lt;code&gt;Vary: Accept-Encoding&lt;/code&gt; on shared caches can mix encodings across clients and produce flaky lab runs that look like random PageSpeed noise. When the score drops after the toggle, compare Time to First Byte and the server-response audit before chasing image formats again.&lt;/p&gt;
&lt;h3 id=&quot;what-to-fix-next-when-the-lcp-element-is-not-a-text-file&quot;&gt;What to fix next when the LCP element is not a text file&lt;/h3&gt;
&lt;p&gt;Once Content-Encoding looks correct on the critical path, return to ordinary LCP triage. Identify the LCP element. If it is an image, check discovery (preload or early HTML), format and dimensions, and whether &lt;code&gt;loading=&quot;lazy&quot;&lt;/code&gt; was applied to the hero by mistake. If Time to First Byte is high, compression will not hide a cold origin, an uncached HTML document, or a slow application query. If render-blocking CSS and JavaScript dominate, shrinking them with Brotli helps a little; removing or deferring work that is not needed for first paint usually helps more.&lt;/p&gt;
&lt;p&gt;Keep compression and caching as paired delivery checks rather than as a substitute for element-level work. Cache-Control decides whether repeat views reuse bytes; Brotli and gzip decide how small the first download of text is. Neither replaces a late LCP image or a client-only render of the hero. For agencies, a clear client update is: compression is done and verified; the remaining LCP risk is named (image, Time to First Byte, or blocking scripts) with an owner and a retest plan.&lt;/p&gt;
&lt;h3 id=&quot;how-agencies-verify-compression-and-lcp-across-a-client-portfolio&quot;&gt;How agencies verify compression and LCP across a client portfolio&lt;/h3&gt;
&lt;p&gt;One &lt;code&gt;curl&lt;/code&gt; on staging is not enough evidence across a client portfolio. After deploys that touch CDN, origin, or build output, re-check Content-Encoding on each client’s homepage and other priority pages, then re-run the same lab profile you use for monthly reporting. Scheduled PageSpeed monitoring catches the case where Brotli is on in one region and missing in another, or where a theme update reintroduces uncompressed CSS while the dashboard still says compression is enabled. Pair those runs with a short note in the monthly report: encoding verified on the document and main CSS/JavaScript; LCP element and Time to First Byte trend unchanged or improved.&lt;/p&gt;
&lt;p&gt;That habit keeps the compression ticket from being closed while LCP is still slow. It also stops the next quarterly review from reopening “we turned Brotli on months ago” when the real issue was always the hero image or the origin. Include compression checks in the same monitoring cadence you already use for Core Web Vitals regressions. A separate ritual that nobody opens after launch week does not help.&lt;/p&gt;
&lt;h3 id=&quot;faq-1&quot;&gt;FAQ&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Does Brotli always improve Largest Contentful Paint?&lt;/strong&gt;&lt;br&gt;
No. It can shorten download time for text on the critical path when that download was a real bottleneck. It will not fix a slow LCP image, a late-discovered hero, or a high Time to First Byte caused by origin work. Before-and-after lab runs on the same profile show whether the change mattered.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why does Enable text compression still fail after we turned Brotli on?&lt;/strong&gt;&lt;br&gt;
The Lighthouse audit looks at individual text resources above a size threshold, not at a single CDN toggle. HTML may be compressed while CSS or JavaScript is not, or the lab path may differ from the URL you checked by hand. Confirm &lt;code&gt;Content-Encoding&lt;/code&gt; on each flagged URL.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Can Brotli make PageSpeed scores worse?&lt;/strong&gt;&lt;br&gt;
Yes. High-quality dynamic compression on every HTML response can raise Time to First Byte. Double compression and compressing already-compressed media waste CPU without helping LCP. Prefer precompressed static assets and moderate settings for dynamic HTML, then retest.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Is gzip still needed if Brotli is enabled?&lt;/strong&gt;&lt;br&gt;
Yes as a fallback. Keep gzip for clients or hops that do not take &lt;code&gt;br&lt;/code&gt;. Verify both encodings on the homepage and other priority pages rather than assuming the dashboard covers every path after a CDN or origin change.&lt;/p&gt;
&lt;h3 id=&quot;cta-1&quot;&gt;CTA&lt;/h3&gt;
&lt;p&gt;If the toggle is green and LCP is still slow, treat compression as verified delivery work and name the next bottleneck in plain language. Confirm encoding on the critical path, then put image discovery, Time to First Byte, and render-blocking scripts on the work item with an owner. For enablement detail and MIME allow-lists, use the Watcher compression guide linked above; for caching that sticks beside those bytes, use the Cache-Control piece. When you need scheduled lab history across many client URLs so the next deploy cannot silently drop &lt;code&gt;Content-Encoding&lt;/code&gt;, run continuous PageSpeed checks in &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/?utm_source=hashnode&amp;amp;utm_medium=referral&amp;amp;utm_campaign=brotli-on-pagespeed-lcp-still-slow&quot;&gt;Apogee Watcher&lt;/a&gt; rather than another one-off Insights paste.&lt;/p&gt;
&lt;h3 id=&quot;references-1&quot;&gt;References&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/brotli-gzip-compression-pagespeed&quot;&gt;Brotli and Gzip Compression: Shrink Text Assets Without Breaking PageSpeed Scores&lt;/a&gt; (Apogee Watcher)&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/cache-control-headers-for-web-performance-cdn-and-browser-caching-that-sticks&quot;&gt;Cache-Control Headers for Web Performance: CDN and Browser Caching That Sticks&lt;/a&gt; (Apogee Watcher)&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://developer.chrome.com/docs/lighthouse/performance/uses-text-compression&quot;&gt;Enable text compression&lt;/a&gt; (Chrome for Developers)&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://web.dev/articles/lcp&quot;&gt;Largest Contentful Paint (LCP)&lt;/a&gt; (web.dev)&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://developer.mozilla.org/en-US/docs/Glossary/Brotli&quot;&gt;Brotli&lt;/a&gt; (MDN Web Docs)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;Originally published on &lt;a rel=&quot;nofollow&quot; href=&quot;https://devlog.apogeewatcher.com/brotli-compression-on-pagespeed-lcp-still-slow&quot;&gt;Hashnode&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/30909/brotli-compression-is-on-why-is-pagespeed-lcp-still-slow</guid>
<pubDate>Tue, 13 Oct 2026 08:49:35 +0000</pubDate>
</item>
<item>
<title>Why is PageSpeed Insights worse than my local Lighthouse score?</title>
<link>https://coderlegion.com/29495/why-is-pagespeed-insights-worse-than-my-local-lighthouse-score</link>
<description>&lt;p&gt;Same URL, same Lighthouse engine: different CPU, throttling, and cache. Compare tools fairly instead of merging the scores.&lt;/p&gt;
&lt;p&gt;You run Lighthouse in Chrome DevTools on a client URL and see Performance 94. You paste the same URL into PageSpeed Insights and the lab Performance score drops to the sixties. The audits look related. The numbers do not. Neither result is “lying.” They ran the same Lighthouse family of audits on different machines, with different throttling behaviour, and often with different cache and extension state.&lt;/p&gt;
&lt;p&gt;That gap shows up constantly in agency Slack threads and client calls. People then optimise against the friendlier number, or treat PageSpeed Insights as broken. What follows explains why PageSpeed Insights lab data is often worse than a local Lighthouse run, how to compare fairly, and which result to trust for client work. For how Lighthouse turns metrics into a score, see &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/how-lighthouse-performance-scores-recorded-calculated?utm_source=hashnode&amp;amp;utm_medium=referral&amp;amp;utm_campaign=why-pagespeed-insights-worse-than-local-lighthouse&quot;&gt;How Lighthouse Performance Scores Are Recorded and Calculated&lt;/a&gt;. For when one-off PageSpeed Insights checks stop being enough, see &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/pagespeed-insights-vs-automated-monitoring-when-manual-checks-arent-enough?utm_source=hashnode&amp;amp;utm_medium=referral&amp;amp;utm_campaign=why-pagespeed-insights-worse-than-local-lighthouse&quot;&gt;PageSpeed Insights vs Automated Monitoring&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;same-lighthouse-engine-different-machines&quot;&gt;Same Lighthouse engine, different machines&lt;/h3&gt;
&lt;p&gt;PageSpeed Insights lab results are Lighthouse runs on Google’s shared infrastructure. Chrome DevTools Lighthouse and the Lighthouse CLI run on your laptop. The audit set is related. The CPU is not.&lt;/p&gt;
&lt;p&gt;Lighthouse records a &lt;strong&gt;benchmarkIndex&lt;/strong&gt; (device score) that describes how fast the host can run JavaScript before the audited page load. A powerful developer machine often scores much higher than the PageSpeed Insights workers. Mobile runs also apply a CPU slowdown (commonly described as about 4×) so the lab approximates mid-tier phones. Four times a fast laptop is still faster than four times a slower shared worker. Long tasks, Total Blocking Time, and Interaction to Next Paint proxies move first when the host is slower. Largest Contentful Paint and other paint timings can move too when layout and script work stretch.&lt;/p&gt;
&lt;p&gt;Network path and test location add another layer. PageSpeed Insights picks from a small set of regions. Your laptop sits on your office fibre next to a nearby CDN edge. Cold loads on a distant worker see different latency even before CPU differences matter.&lt;/p&gt;
&lt;p&gt;So a lower PageSpeed Insights lab score does not prove the site “got worse overnight.” It often proves you compared two hosts.&lt;/p&gt;
&lt;h3 id=&quot;why-total-blocking-time-jumps-on-pagespeed-insights&quot;&gt;Why Total Blocking Time jumps on PageSpeed Insights&lt;/h3&gt;
&lt;p&gt;Total Blocking Time is especially sensitive to host speed. It sums the portions of long tasks that exceed 50 milliseconds during page load. On a fast local CPU, many tasks finish just under that line and never enter Total Blocking Time. On a slower PageSpeed Insights worker, the same work crosses 50 milliseconds and the metric spikes. Performance score then falls even when First Contentful Paint only moved a little.&lt;/p&gt;
&lt;p&gt;That pattern is well documented in developer threads and Lighthouse discussions: throttling and slower hosts push borderline tasks over the threshold. Simulated throttling (PageSpeed Insights lab default) is also not the same as packet-level throttling used by some other lab tools. Treat PageSpeed Insights lab numbers as one environment, not as a perfect replay of your MacBook.&lt;/p&gt;
&lt;h3 id=&quot;local-pollution-extensions-cache-and-warm-state&quot;&gt;Local pollution: extensions, cache, and warm state&lt;/h3&gt;
&lt;p&gt;Local Lighthouse can look better for reasons that have nothing to do with the production HTML.&lt;/p&gt;
&lt;p&gt;Chrome extensions inject scripts and change network behaviour. A warm disk cache and service worker can skip work that a cold PageSpeed Insights load always pays. Cookie banners and consent layers may already be dismissed on your profile. Antivirus, VPN, and other processes on the machine add noise. DevTools may warn when it detects conditions that skew the audit; PageSpeed Insights starts from a cleaner cold profile on Google’s side.&lt;/p&gt;
&lt;p&gt;Use an Incognito window with extensions disabled, or the Lighthouse CLI against a clean profile, when you need a local baseline. Even then, expect residual host-speed differences versus PageSpeed Insights. A clean local profile removes extension noise; it does not turn your laptop into Google’s lab workers.&lt;/p&gt;
&lt;h3 id=&quot;do-not-mix-pagespeed-insights-field-data-with-local-lab&quot;&gt;Do not mix PageSpeed Insights field data with local lab&lt;/h3&gt;
&lt;p&gt;PageSpeed Insights shows two stories on one page. The top block is Chrome UX Report field data when enough real Chrome users visited the origin or URL. The lower block is a fresh Lighthouse lab run.&lt;/p&gt;
&lt;p&gt;Your local Lighthouse score is lab only. Comparing a local Performance score to the field Core Web Vitals categories is a category error. Field windows cover days of real devices and networks. Lab is one controlled load. Lab-versus-field reconciliation is a separate topic; here the focus is local lab versus PageSpeed Insights lab.&lt;/p&gt;
&lt;p&gt;If field looks healthier than PageSpeed Insights lab, users may be on faster devices, revisit with cache, or you may be reading origin-level field against a URL-level lab run. Calibrate, do not average the two into one fake “truth.”&lt;/p&gt;
&lt;h3 id=&quot;how-to-compare-fairly-and-what-to-trust-for-client-work-&quot;&gt;How to compare fairly (and what to trust for client work)&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Source &lt;/th&gt;&lt;th&gt;What it measures &lt;/th&gt;&lt;th&gt;Best use&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Chrome DevTools / local CLI &lt;/td&gt;&lt;td&gt;Lab on your machine &lt;/td&gt;&lt;td&gt;Before/after while debugging the same URL&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;PageSpeed Insights lab &lt;/td&gt;&lt;td&gt;Lab on Google’s workers &lt;/td&gt;&lt;td&gt;Shareable cold-load baseline close to what clients paste&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;PageSpeed Insights field (CrUX) &lt;/td&gt;&lt;td&gt;Real-user Core Web Vitals &lt;/td&gt;&lt;td&gt;Trend and eligibility, not a Lighthouse score twin&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Rules that keep agencies from mixing incompatible scores:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Compare before and after on the same tool.&lt;/strong&gt; Local 94 → local 88 after a change is useful. Local 94 versus PageSpeed Insights 61 is not a regression proof.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Match strategy.&lt;/strong&gt; Mobile versus mobile. Desktop versus desktop.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Prefer cold loads&lt;/strong&gt; when you claim a public score. Clear cache or use a clean profile locally.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Read the device score / environment notes&lt;/strong&gt; in the Lighthouse JSON when you need to explain a gap to a technical lead.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;For client reporting, prefer a stable lab path.&lt;/strong&gt; Scheduled PageSpeed Insights-style runs from a monitoring product reduce “my laptop versus your laptop” arguments. Spot checks still help debugging; they are a weak single source of truth for retainers.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;DebugBear’s comparison of PageSpeed Insights and Lighthouse, and Google’s own Lighthouse variability notes, make the same point: synthetic scores depend on CPU, location, Chrome version, and throttling method. Absolute equality across tools is the wrong goal. Directional agreement on the same tool is the right one.&lt;/p&gt;
&lt;h3 id=&quot;faq-2&quot;&gt;FAQ&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Is PageSpeed Insights “more accurate” than local Lighthouse?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;For cold-load lab diagnostics that clients can reopen in a browser, PageSpeed Insights is often the better shared reference. For day-to-day engineering, local Lighthouse before/after on the same machine is faster and still valid. Neither replaces field Core Web Vitals when you need real-user truth.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why does my local Lighthouse match PageSpeed Insights sometimes?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;When host speeds are closer, the URL is light on main-thread work, or the runs simply land nearer each other, gaps shrink. Heavy JavaScript and layout work widen them. Treat occasional agreement as luck on a light page, not proof that the two environments are interchangeable.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Should I raise local CPU slowdown until scores match PageSpeed Insights?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;You can experiment with CLI throttling for research. Do not treat a personalised slowdown as a contract with the client unless everyone agrees that environment is the baseline. Document the tool and settings you will use in the retainer.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Does a better local score mean Search Console will improve?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Not by itself. Search Console and Chrome UX Report track field data. Lab wins help you find fixes; field windows confirm whether real users felt them.&lt;/p&gt;
&lt;h3 id=&quot;what-to-do-next&quot;&gt;What to do next&lt;/h3&gt;
&lt;p&gt;Pick one money URL. Run Lighthouse twice locally in a clean profile and note the spread. Run PageSpeed Insights lab on the same URL and strategy. Write down host differences instead of merging the scores. Put the PageSpeed Insights lab number (or a scheduled monitoring run) in the client pack when you need a shareable baseline, and keep local Lighthouse for the fix loop.&lt;/p&gt;
&lt;p&gt;If you manage many client origins, automate the PageSpeed Insights-shaped lab path so every site uses the same cold-load recipe. That is the operational answer to “whose Lighthouse do we believe?”: agree the environment once, then track change inside it. Spot laptop runs stay useful for debugging; they should not be the only number in the monthly pack.&lt;/p&gt;
&lt;h3 id=&quot;references-2&quot;&gt;References&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.debugbear.com/blog/why-is-my-lighthouse-score-different-from-pagespeed-insights&quot;&gt;PageSpeed Insights vs. Lighthouse: What's the Difference?&lt;/a&gt; (DebugBear)&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/GoogleChrome/lighthouse/blob/main/docs/variability.md&quot;&gt;Lighthouse variability / scoring environment&lt;/a&gt; (Chrome Lighthouse docs)&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://stackoverflow.com/questions/75326384/why-is-lighthouse-data-reported-via-the-pagespeed-insights-api-consistently-diff&quot;&gt;Why Lighthouse via PageSpeed Insights API differs from CLI&lt;/a&gt; (Stack Overflow)&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://stackoverflow.com/questions/78156164/why-is-tbt-on-psi-so-different-from-my-local-machine&quot;&gt;Why TBT on PageSpeed Insights differs from a local machine&lt;/a&gt; (Stack Overflow)&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/how-lighthouse-performance-scores-recorded-calculated&quot;&gt;How Lighthouse Performance Scores Are Recorded and Calculated&lt;/a&gt; (Apogee Watcher)&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/pagespeed-insights-vs-automated-monitoring-when-manual-checks-arent-enough&quot;&gt;PageSpeed Insights vs Automated Monitoring: When Manual Checks Aren't Enough&lt;/a&gt; (Apogee Watcher)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;Originally published on &lt;a rel=&quot;nofollow&quot; href=&quot;https://devlog.apogeewatcher.com/why-pagespeed-insights-worse-than-local-lighthouse&quot;&gt;Hashnode&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/29495/why-is-pagespeed-insights-worse-than-my-local-lighthouse-score</guid>
<pubDate>Fri, 02 Oct 2026 07:54:07 +0000</pubDate>
</item>
<item>
<title>How to set performance budgets that CI and clients both keep</title>
<link>https://coderlegion.com/29205/how-to-set-performance-budgets-that-ci-and-clients-both-keep</link>
<description>&lt;p&gt;Same LCP and CLS numbers in the merge gate and the retainer review — not two conflicting greens.&lt;/p&gt;
&lt;p&gt;Lighthouse CI can report green on a pull request while the client’s monthly PageSpeed pack still shows amber on Largest Contentful Paint. Both results can be “correct.” They measured different URLs, different strategies, or different thresholds that nobody reconciled when the retainer started. That mismatch is expensive: engineering trusts the gate, sponsors distrust the report, and the agency spends the call explaining why two greens disagree.&lt;/p&gt;
&lt;p&gt;Web performance budgets only work when the merge gate and the client review speak the same language. What follows is the agency ritual that keeps those numbers aligned: pick thresholds once, wire them into CI for protection, and reuse them on production schedules for the retainer. For the CI plumbing itself, use &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/how-to-set-up-performance-budgets-in-ci-cd-pipelines?utm_source=hashnode&amp;amp;utm_medium=referral&amp;amp;utm_campaign=how-to-set-performance-budgets-ci-and-clients-both-keep&quot;&gt;How to Set Up Performance Budgets in CI/CD Pipelines&lt;/a&gt;. For a reusable threshold sheet, use &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/performance-budget-thresholds-template?utm_source=hashnode&amp;amp;utm_medium=referral&amp;amp;utm_campaign=how-to-set-performance-budgets-ci-and-clients-both-keep&quot;&gt;Performance Budget Thresholds Template&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;why-ci-budgets-and-client-budgets-drift-apart&quot;&gt;Why CI budgets and client budgets drift apart&lt;/h3&gt;
&lt;p&gt;Teams usually invent two documents by accident. Engineering owns a Lighthouse CI assertion file tuned to preview URLs. Account leads own a slide that still says “keep PageSpeed healthy” without naming LCP, Interaction to Next Paint, or Cumulative Layout Shift. After a few sprints the CI file tightens, the deck softens, and nobody notices until a sponsor asks why last week’s merge was green and this week’s field window is not.&lt;/p&gt;
&lt;p&gt;Three drift patterns show up often:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Different URLs.&lt;/strong&gt; CI protects &lt;code&gt;/&lt;/code&gt; on the preview host. The retainer reports &lt;code&gt;/checkout&lt;/code&gt; on production.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Different clocks.&lt;/strong&gt; CI is lab-only. The client pack mixes CrUX categories without labelling the window.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Different owners.&lt;/strong&gt; Developers change assertions without telling account leads; account leads invent “good enough” bands for a sales deck.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Performance budgets are the contract that stops that drift. &lt;a rel=&quot;nofollow&quot; href=&quot;https://web.dev/articles/performance-budgets-101&quot;&gt;web.dev’s performance budgets 101&lt;/a&gt; frames them as limits you set before you ship. Agencies need one more step: the same limits must survive the handoff from demo to retained delivery.&lt;/p&gt;
&lt;h3 id=&quot;one-threshold-language-both-sides-keep&quot;&gt;One threshold language both sides keep&lt;/h3&gt;
&lt;p&gt;Start with Core Web Vitals in the same units Google already publishes, then add supporting lab metrics only if someone will act on them.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Metric &lt;/th&gt;&lt;th&gt;Example mobile budget (lab) &lt;/th&gt;&lt;th&gt;Why both sides care&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;LCP &lt;/td&gt;&lt;td&gt;≤ 2.5 s &lt;/td&gt;&lt;td&gt;Hero and checkout speed sponsors recognise&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;INP &lt;/td&gt;&lt;td&gt;≤ 200 ms &lt;/td&gt;&lt;td&gt;Interaction regressions after tag or SPA changes&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;CLS &lt;/td&gt;&lt;td&gt;≤ 0.1 &lt;/td&gt;&lt;td&gt;Layout shift from banners, embeds, late fonts&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Performance score (optional) &lt;/td&gt;&lt;td&gt;≥ 90 on priority URLs &lt;/td&gt;&lt;td&gt;Useful as a CI gate; weaker as the only client KPI&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Write those numbers into a shared sheet once, with owners and review cadence. Lab budgets belong in CI assertions and in scheduled production tests. Field (CrUX) categories sit beside them as a labelled second row, not as a silent override of the lab gate. When CrUX has no data for an origin, say so plainly rather than inventing a green badge from lab alone.&lt;/p&gt;
&lt;p&gt;Weight and request-count budgets still help on image-heavy templates. Keep them secondary to CWV language in client conversations unless the engineering team already lives in kilobytes. Official orientation for Lighthouse-based budgets sits in &lt;a rel=&quot;nofollow&quot; href=&quot;https://web.dev/articles/use-lighthouse-for-performance-budgets&quot;&gt;Use Lighthouse for performance budgets&lt;/a&gt;; MDN’s &lt;a rel=&quot;nofollow&quot; href=&quot;https://developer.mozilla.org/en-US/docs/Web/Performance/Guides/Performance_budgets&quot;&gt;Performance budgets&lt;/a&gt; guide is a solid companion for the same idea.&lt;/p&gt;
&lt;h3 id=&quot;the-demo-retained-budget-ritual&quot;&gt;The demo → retained budget ritual&lt;/h3&gt;
&lt;p&gt;Agencies that keep budgets sticky usually run a short ceremony when a new client starts, then refuse to invent new bands every quarter.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. Demo with production-shaped URLs.&lt;/strong&gt; Show the money paths you will monitor, not only the homepage. Capture baseline lab numbers and note field availability.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. Agree thresholds in writing.&lt;/strong&gt; Use the shared sheet. Name mobile and desktop if both matter. Name who owns a breach (agency sprint vs client tag team).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. Mirror into Lighthouse CI.&lt;/strong&gt; Assertions protect merges on the preview URLs that map to those money paths. Do not encode a vanity homepage score that production never measures.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4. Mirror into production schedules.&lt;/strong&gt; The same LCP / INP / CLS lines become the green and red language in alerts and monthly reports. Scheduled PageSpeed Insights (or equivalent) runs keep history; budgets decide when humans get interrupted.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;5. Review on a calendar, not on vibes.&lt;/strong&gt; Quarterly is enough for most retainers unless a redesign is live. Change a threshold only with a written reason both sides can find later.&lt;/p&gt;
&lt;p&gt;That ritual is the product of the retainer. Tools differ. DIY scripts, portfolio monitors, and CI plugins all work when the sheet is the source of truth. Apogee Watcher is built for the production side of that loop (schedules, budgets, alerts across organisations). Keep Lighthouse CI thin for merge gates either way.&lt;/p&gt;
&lt;h3 id=&quot;what-stays-in-ci-versus-what-stays-on-production-schedules&quot;&gt;What stays in CI versus what stays on production schedules&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Job &lt;/th&gt;&lt;th&gt;Belongs in Lighthouse CI &lt;/th&gt;&lt;th&gt;Belongs on production monitoring&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Block a bad merge &lt;/td&gt;&lt;td&gt;Yes &lt;/td&gt;&lt;td&gt;No&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Catch regressions after deploy or tag changes &lt;/td&gt;&lt;td&gt;Weak alone &lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Multi-tenant client reporting &lt;/td&gt;&lt;td&gt;No &lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;CrUX / field context &lt;/td&gt;&lt;td&gt;Rarely &lt;/td&gt;&lt;td&gt;Yes, labelled&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Same LCP ≤ 2.5 s language &lt;/td&gt;&lt;td&gt;Yes (assertions) &lt;/td&gt;&lt;td&gt;Yes (budgets + reports)&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;CI answers: “May this change ship?” Production monitoring answers: “Is the live portfolio still inside the contract?” Confusing the two jobs produces either enormous workflows or neglected configurations. Keep both; share the threshold language. When account leads can point at the same LCP band the pipeline just enforced, the retainer review stops sounding like two different products.&lt;/p&gt;
&lt;h3 id=&quot;faq-3&quot;&gt;FAQ&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;What are performance budgets in a web performance sense?&lt;/strong&gt;&lt;br&gt;
Numeric limits for page experience (and sometimes weight or request counts) that you set before shipping and reuse when something regresses. In agency retainers they should match the Core Web Vitals language you put in client reports.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How do performance budget thresholds differ from a vague “keep PageSpeed high” promise?&lt;/strong&gt;&lt;br&gt;
Thresholds name metric, strategy, URL set, and pass/fail band. Vague promises invite taste debates. Use a shared template so account leads are not inventing bands per deck.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Should Lighthouse CI performance budgets match production budgets exactly?&lt;/strong&gt;&lt;br&gt;
Match the metrics and bands that matter commercially. Preview hosts may differ slightly from production; document that. Do not run a 95 score gate in CI while the retainer quietly accepts 70 on checkout.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Do Core Web Vitals budgets replace Search Console?&lt;/strong&gt;&lt;br&gt;
No. Budgets organise lab (and optionally field) pass/fail for delivery. Search Console remains a field and indexing source for many SEO conversations. Use both with clocks labelled.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Who owns a budget breach?&lt;/strong&gt;&lt;br&gt;
Decide at kick-off. Tag-manager and marketing-pixel breaches often sit with the client. Theme and critical-path breaches often sit with the agency. Write the split once so the alert does not become a blame meeting.&lt;/p&gt;
&lt;h3 id=&quot;cta-2&quot;&gt;CTA&lt;/h3&gt;
&lt;p&gt;Pick one retainer client this week. Export or write a one-page threshold sheet for three money-path URLs, wire the same LCP / INP / CLS bands into Lighthouse CI, and reuse those bands on whatever production schedule you already run. When you need the CI assertion path in detail, follow &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/how-to-set-up-performance-budgets-in-ci-cd-pipelines?utm_source=hashnode&amp;amp;utm_medium=referral&amp;amp;utm_campaign=how-to-set-performance-budgets-ci-and-clients-both-keep&quot;&gt;performance budgets in CI/CD pipelines&lt;/a&gt;. When you need a blank sheet, use the &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/performance-budget-thresholds-template?utm_source=hashnode&amp;amp;utm_medium=referral&amp;amp;utm_campaign=how-to-set-performance-budgets-ci-and-clients-both-keep&quot;&gt;performance budget thresholds template&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Portfolio schedules and budget alerts without a private spreadsheet of PageSpeed tabs are what &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/sign-up?utm_source=hashnode&amp;amp;utm_medium=referral&amp;amp;utm_campaign=how-to-set-performance-budgets-ci-and-clients-both-keep&quot;&gt;Apogee Watcher&lt;/a&gt; is built for. Keep your merge gates. The sheet you agree with the client is still the source of truth either way.&lt;/p&gt;
&lt;h3 id=&quot;references-3&quot;&gt;References&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://web.dev/articles/performance-budgets-101&quot;&gt;Performance budgets 101&lt;/a&gt; (web.dev)&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://web.dev/articles/use-lighthouse-for-performance-budgets&quot;&gt;Use Lighthouse for performance budgets&lt;/a&gt; (web.dev)&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://developer.mozilla.org/en-US/docs/Web/Performance/Guides/Performance_budgets&quot;&gt;Performance budgets&lt;/a&gt; (MDN)&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://addyosmani.com/blog/performance-budgets/&quot;&gt;Start Performance Budgeting&lt;/a&gt; (Addy Osmani)&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/how-to-set-up-performance-budgets-in-ci-cd-pipelines&quot;&gt;How to Set Up Performance Budgets in CI/CD Pipelines&lt;/a&gt; (Apogee Watcher)&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/performance-budget-thresholds-template&quot;&gt;Performance Budget Thresholds Template&lt;/a&gt; (Apogee Watcher)&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://developers.google.com/search/docs/appearance/core-web-vitals&quot;&gt;Understanding Core Web Vitals and Google search results&lt;/a&gt; (Google Search Central)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;Originally published on &lt;a rel=&quot;nofollow&quot; href=&quot;https://devlog.apogeewatcher.com/how-to-set-performance-budgets-ci-and-clients-both-keep&quot;&gt;Hashnode&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/29205/how-to-set-performance-budgets-that-ci-and-clients-both-keep</guid>
<pubDate>Wed, 30 Sep 2026 07:16:40 +0000</pubDate>
</item>
<item>
<title>Google Lighthouse Score Explained: How Scoring Works</title>
<link>https://coderlegion.com/27089/google-lighthouse-score-explained-how-scoring-works</link>
<description>&lt;p&gt;A Google Lighthouse score is a lab Performance number from 0 to 100 for one controlled run. Scoring does not average raw milliseconds. Each metric is mapped through an HTTP Archive curve, then weighted into one score for a single URL and one device strategy.&lt;/p&gt;
&lt;p&gt;Agencies usually meet that number as the green or amber circle in PageSpeed Insights. Clients treat it as &quot;Google speed.&quot; It is neither a ranking factor by itself nor a field Core Web Vitals percentile. It is recorded under simulated conditions, then calculated with documented weights that change across Lighthouse majors.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; Record lab metrics in a throttled run, convert each to a 0–100 metric score, apply Lighthouse 10 weights (TBT 30%, LCP and CLS 25% each, FCP and Speed Index 10% each), and report the blend as lab only. Keep CrUX and Search Console on a separate slide. Chrome’s &lt;a rel=&quot;nofollow&quot; href=&quot;https://developer.chrome.com/docs/lighthouse/performance/performance-scoring&quot;&gt;Lighthouse performance scoring&lt;/a&gt; guide is the source of truth; what follows is the agency translation, including a worked example and FAQ.&lt;/p&gt;
&lt;h2 id=&quot;what-a-lighthouse-performance-score-actually-is&quot; class=&quot;scroll-mt-24&quot;&gt;What a Lighthouse Performance score actually is&lt;/h2&gt;
&lt;p&gt;The Performance score is a single 0–100 summary for one lab run of one URL under one device strategy (mobile or desktop). It is not a ranking factor by itself. It is not a rolling average of real visitors. Opportunities and Diagnostics in the report do not add points directly; they explain ways the underlying metrics might improve, which can raise the score indirectly when those metrics move.&lt;/p&gt;
&lt;p&gt;Colour bands in the docs are simple: 0–49 poor (red), 50–89 needs improvement (orange), 90–100 good (green). A perfect 100 is unusually hard. Moving from 99 to 100 can need as much metric improvement as moving from 90 to 94. For client language, “good” means a lab run that cleared 90 under that profile, not that every user on every network had a green experience.&lt;/p&gt;
&lt;p&gt;PageSpeed Insights uses Lighthouse for the lab block. When people say “the PageSpeed Insights score,” they usually mean that lab Performance category, sometimes while looking at a CrUX field panel on the same screen. Keep those two stories separate in every deck.&lt;/p&gt;
&lt;h2 id=&quot;how-lighthouse-records-lab-metrics-in-a-controlled-run&quot; class=&quot;scroll-mt-24&quot;&gt;How Lighthouse records lab metrics in a controlled run&lt;/h2&gt;
&lt;p&gt;Recording comes first. Lighthouse (and PageSpeed Insights lab mode) loads the URL in a controlled environment: a chosen form factor, simulated network and CPU throttling for typical mobile profiles, and a single navigation. During that load it measures timings and layout behaviour. Common Performance metrics include First Contentful Paint (FCP), Speed Index (SI), Largest Contentful Paint (LCP), Total Blocking Time (TBT), and Cumulative Layout Shift (CLS). Diagnostics such as Time to First Byte (TTFB) may appear as supporting detail. None of those values are taken from real visitors in that run.&lt;/p&gt;
&lt;p&gt;The lab profile matters. Mobile and desktop use different throttling and, since Lighthouse 6, different scoring curves so desktop is not scored on mobile HTTP Archive distributions. Running on a quiet office machine with extensions disabled still differs from a busy shared CI worker. Chrome documents common causes of score fluctuation: ads and A/B tests, routing changes, device power, extensions, antivirus. Treat a single paste as a sample from a distribution, not as the only possible score for that URL.&lt;/p&gt;
&lt;p&gt;Scheduled monitoring reduces the “two screenshots, no baseline” problem. You still measure lab conditions, but you compare like with like over time. That is the operational gap we described in &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/pagespeed-insights-vs-automated-monitoring-when-manual-checks-arent-enough&quot;&gt;PageSpeed Insights versus automated monitoring&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;how-lighthouse-calculates-the-0-100-performance-score&quot; class=&quot;scroll-mt-24&quot;&gt;How Lighthouse calculates the 0–100 Performance score&lt;/h2&gt;
&lt;p&gt;Calculation is a second step. Lighthouse does not average raw milliseconds into one number. For each metric it maps the recorded value onto a 0–100 metric score using a log-normal scoring curve calibrated from HTTP Archive site data. Those metric scores stay under the hood in the usual report UI. The visible Performance score is then a weighted average of the metric scores.&lt;/p&gt;
&lt;p&gt;Chrome describes the curve control points clearly. The 25th percentile of HTTP Archive data for a metric maps to a metric score of 50. The 8th percentile maps to 90 (the “good” control point). Between roughly 0.50 and 0.92 the relationship is nearly linear; near 0.96 returns diminish and further metric gains buy less score. Exploring a metric in the &lt;a rel=&quot;nofollow&quot; href=&quot;https://googlechrome.github.io/lighthouse/scorecalc/&quot;&gt;Lighthouse scoring calculator&lt;/a&gt; is the fastest way to see how a raw LCP or TBT value becomes a metric score before weights apply.&lt;/p&gt;
&lt;p&gt;Because the curves come from real-site distributions, “good” is relative to the web as captured in HTTP Archive, not to an arbitrary round number your client invented in a brand guideline. When Lighthouse major versions change weights or curves, historical scores need a footnote. Always cite the Lighthouse version your tool used when you compare quarters.&lt;/p&gt;
&lt;h2 id=&quot;lighthouse-scoring-weights-lighthouse-10&quot; class=&quot;scroll-mt-24&quot;&gt;Lighthouse scoring weights (Lighthouse 10)&lt;/h2&gt;
&lt;p&gt;Chrome’s documented &lt;strong&gt;Lighthouse 10&lt;/strong&gt; weights for the Performance score are:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Weight&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;First Contentful Paint (FCP)&lt;/td&gt;
&lt;td&gt;10%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Speed Index (SI)&lt;/td&gt;
&lt;td&gt;10%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Largest Contentful Paint (LCP)&lt;/td&gt;
&lt;td&gt;25%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Total Blocking Time (TBT)&lt;/td&gt;
&lt;td&gt;30%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cumulative Layout Shift (CLS)&lt;/td&gt;
&lt;td&gt;25%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;TBT carries the largest single weight. LCP and CLS share 25% each. FCP and Speed Index are lighter. Earlier majors differed; Lighthouse 8 still weighted Time to Interactive and used a different CLS weight. Verify the table for the version you ship in CI or see in PageSpeed Insights, and re-check the calculator when Google publishes a new major.&lt;/p&gt;
&lt;p&gt;INP may appear in field tooling and in some report contexts, but the lab Performance blend documented for Lighthouse 10 emphasises &lt;strong&gt;TBT&lt;/strong&gt; as the interactivity proxy inside the score. Do not tell a client that “INP is 30% of the Lighthouse score.” Point them at TBT for lab scoring and at field INP for CrUX and Search Console when samples exist. Metric definitions live in &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/lcp-inp-cls-what-each-core-web-vital-means-and-how-to-fix-it&quot;&gt;LCP, INP, and CLS explained&lt;/a&gt;; field interactivity detail is in our &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/understanding-inp-newest-core-web-vital&quot;&gt;INP guide&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;worked-example-from-metric-scores-to-a-performance-number&quot; class=&quot;scroll-mt-24&quot;&gt;Worked example: from metric scores to a Performance number&lt;/h2&gt;
&lt;p&gt;Suppose a mobile lab run produces these &lt;strong&gt;metric scores&lt;/strong&gt; (already mapped through the curves; not raw milliseconds): FCP 90, Speed Index 85, LCP 70, TBT 60, CLS 95. Apply the Lighthouse 10 weights:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;FCP: 90 × 0.10 = 9.0&lt;/li&gt;
&lt;li&gt;Speed Index: 85 × 0.10 = 8.5&lt;/li&gt;
&lt;li&gt;LCP: 70 × 0.25 = 17.5&lt;/li&gt;
&lt;li&gt;TBT: 60 × 0.30 = 18.0&lt;/li&gt;
&lt;li&gt;CLS: 95 × 0.25 = 23.75&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Sum ≈ &lt;strong&gt;76.8&lt;/strong&gt;, which rounds to a Performance score in the mid-70s (needs improvement). The same raw LCP in milliseconds can yield a different metric score when the curve or Lighthouse major changes, so always cite the version beside the number. Open the &lt;a rel=&quot;nofollow&quot; href=&quot;https://googlechrome.github.io/lighthouse/scorecalc/&quot;&gt;Lighthouse scoring calculator&lt;/a&gt; to poke individual levers before you promise a client that &quot;ten points is one easy fix.&quot;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Lighthouse version footnote:&lt;/strong&gt; Weights and curves above follow Chrome’s documented &lt;strong&gt;Lighthouse 10&lt;/strong&gt; Performance scoring. PageSpeed Insights and CI runners may ship a different major. When you compare quarters or tools, record the Lighthouse version (or PageSpeed Insights date) on the report. A five-point swing across a major upgrade can be scoring math, not a regression.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;why-the-performance-score-is-not-the-same-as-core-web-vitals-field-data&quot; class=&quot;scroll-mt-24&quot;&gt;Why the Performance score is not the same as Core Web Vitals field data&lt;/h2&gt;
&lt;p&gt;Field Core Web Vitals come from real Chrome users in the Chrome User Experience Report (CrUX), with Search Console and the PageSpeed Insights field section as common surfaces. Lab Performance scores come from one synthetic navigation. Both can mention LCP and CLS; only the lab score folds in Speed Index and TBT with the weights above. Field INP has no twin inside that Lighthouse 10 weight table.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Question&lt;/th&gt;
&lt;th&gt;Lab Performance score&lt;/th&gt;
&lt;th&gt;Field Core Web Vitals (CrUX)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Who was measured?&lt;/td&gt;
&lt;td&gt;Controlled lab profile&lt;/td&gt;
&lt;td&gt;Real Chrome users (sample)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What number?&lt;/td&gt;
&lt;td&gt;Weighted 0–100 from metric scores&lt;/td&gt;
&lt;td&gt;Percentiles for LCP, INP, CLS (and related)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Interactivity in the blend?&lt;/td&gt;
&lt;td&gt;TBT (lab)&lt;/td&gt;
&lt;td&gt;INP (field)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Good enough for SEO field status?&lt;/td&gt;
&lt;td&gt;No, not by itself&lt;/td&gt;
&lt;td&gt;Search Console / CrUX when eligible&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Useful after a deploy?&lt;/td&gt;
&lt;td&gt;Yes, fast regression signal&lt;/td&gt;
&lt;td&gt;Yes, after the rolling window catches up&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Agencies need both clocks. Lab catches “we broke the template today.” Field answers “Chrome users over ~28 days still feel it.” We covered the field lag in &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/why-core-web-vitals-fix-not-in-crux-yet-28-day-window&quot;&gt;Why your Core Web Vitals fix is not in CrUX yet&lt;/a&gt; and the synthetic versus RUM split in &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/when-to-use-synthetic-vs-real-user-monitoring-performance&quot;&gt;When to use synthetic versus real user monitoring&lt;/a&gt;. Missing field rows are a sampling problem, not proof the lab score is wrong; see &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/pagespeed-insights-no-cls-inp-for-url&quot;&gt;When PageSpeed Insights shows no CLS or INP&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;mid-article-check-run-the-url-you-are-arguing-about&quot; class=&quot;scroll-mt-24&quot;&gt;Mid-article check: run the URL you are arguing about&lt;/h2&gt;
&lt;p&gt;Before you debate a screenshot in Slack, &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/check&quot;&gt;run a free PageSpeed check&lt;/a&gt; on the same URL and strategy (mobile or desktop). Pair the lab Performance score with the metric breakdown, then keep the scoring calculator open so stakeholders see how LCP, TBT, and CLS drive the blend. Scheduled history in Apogee Watcher beats one heroic paste after a tag-manager change.&lt;/p&gt;
&lt;h2 id=&quot;why-lighthouse-scores-fluctuate-between-runs&quot; class=&quot;scroll-mt-24&quot;&gt;Why Lighthouse scores fluctuate between runs&lt;/h2&gt;
&lt;p&gt;Variability is normal. The same URL can move several points between back-to-back runs when ads, consent banners, third-party scripts, or CPU contention differ. Chrome’s variability documentation exists for a reason. For retainers, prefer medians or repeated scheduled runs over a single heroic screenshot. Agree the device strategy (mobile versus desktop) before you argue about a five-point swing.&lt;/p&gt;
&lt;p&gt;CI and local DevTools can also disagree because of Lighthouse version, throttling presets, and whether the environment matches PageSpeed Insights. When you automate audits with coding agents or DevTools workflows, still treat the Performance number as lab math under a stated version. Our note on &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/lighthouse-audits-ai-agents-chrome-devtools&quot;&gt;Lighthouse audits with AI agents&lt;/a&gt; covers the agency gap between one-off agent runs and portfolio schedules. Separate audits such as Baseline Features change Best Practices diagnostics without rewriting the Performance weight table; see &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/lighthouse-baseline-features-audit&quot;&gt;Lighthouse’s Baseline Features audit&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;how-agencies-should-report-lighthouse-scores-to-clients&quot; class=&quot;scroll-mt-24&quot;&gt;How agencies should report Lighthouse scores to clients&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Name the artefact:&lt;/strong&gt; “Lighthouse / PageSpeed Insights lab Performance score,” not “Google’s speed ranking.”&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;State device and version:&lt;/strong&gt; mobile or desktop, and Lighthouse major when known.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Show the drivers:&lt;/strong&gt; LCP, TBT, and CLS usually explain most of the blend under current weights.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Separate field status:&lt;/strong&gt; CrUX / Search Console on their own slide or paragraph.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use trends:&lt;/strong&gt; three or more scheduled runs beat one paste after a deploy.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Open the calculator&lt;/strong&gt; when a stakeholder wants to know how many milliseconds buy the next ten points.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Avoid score chasing at 99–100&lt;/strong&gt; unless the contract truly requires vanity greens; spend engineering time on user-visible LCP and TBT first.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Budgets work better on metric thresholds than on a single Performance integer, because the integer hides which metric moved. Pair score trends with LCP and TBT budgets on money URLs so engineering knows what to fix. A five-point score drop that is all TBT is a different ticket from one that is all CLS.&lt;/p&gt;
&lt;h2 id=&quot;where-apogee-watcher-stores-performance-scores&quot; class=&quot;scroll-mt-24&quot;&gt;Where Apogee Watcher stores Performance scores&lt;/h2&gt;
&lt;p&gt;Apogee Watcher schedules PageSpeed Insights tests across multi-tenant portfolios and stores the lab category scores and metric payloads from those runs for trends, budgets, and alerts. That history is lab data under Google’s PSI/Lighthouse pipeline. It is not a substitute for CrUX percentiles, and it does not claim to weight INP inside the Performance blend.&lt;/p&gt;
&lt;p&gt;Use Watcher when you need the same URLs retested on a cadence after deploys, with mobile and desktop strategies and client-ready charts. Use CrUX and Search Console for field Core Web Vitals when samples exist. Use the scoring calculator when someone asks how the 0–100 number is built. Layer the tools; do not collapse them into one green circle in a slide.&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/sign-up&quot;&gt;Start a free trial&lt;/a&gt; to schedule PageSpeed tests and keep Performance score trends beside metric budgets. Or &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/check&quot;&gt;run a free PageSpeed check&lt;/a&gt; on a priority URL and open the &lt;a rel=&quot;nofollow&quot; href=&quot;https://googlechrome.github.io/lighthouse/scorecalc/&quot;&gt;Lighthouse scoring calculator&lt;/a&gt; beside the result.&lt;/p&gt;
&lt;h2 class=&quot;scroll-mt-24&quot;&gt;FAQ&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;What is a Google Lighthouse score?&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;&lt;p&gt;A Google Lighthouse score usually means the Performance category (0–100) from one lab audit, alongside Accessibility, Best Practices, and SEO category scores. The Performance number is the weighted blend covered here. It is not an average of real-user timings and not a Search Console field status.&lt;/p&gt;&lt;br&gt;
&lt;p&gt;&lt;strong&gt;How does Lighthouse scoring work?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Recording comes first: Lighthouse loads the URL under a fixed device and throttling profile and measures lab metrics (FCP, Speed Index, LCP, TBT, CLS under current docs). Calculation comes second: each metric maps to a 0–100 metric score via log-normal HTTP Archive curves, then those metric scores are weighted into the visible Performance number.&lt;/p&gt;&lt;br&gt;
&lt;p&gt;&lt;strong&gt;What is a good Lighthouse Performance score?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Chrome’s colour bands: 0–49 poor, 50–89 needs improvement, 90–100 good. &quot;Good&quot; means that lab run cleared 90 under that profile, not that every visitor on every network had a green experience. Chasing 99–100 is usually vanity; spend engineering time on user-visible LCP and TBT first.&lt;/p&gt;&lt;br&gt;
&lt;p&gt;&lt;strong&gt;How do lab Lighthouse scores differ from PageSpeed Insights and CrUX?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
PageSpeed Insights shows a Lighthouse lab block and, when eligible, a CrUX field block on the same page. The lab circle is Lighthouse scoring. CrUX is aggregated Chrome field data (percentiles for LCP, INP, CLS), not the weighted 0–100 Performance blend. For when to lean on synthetic lab runs versus real-user monitoring, see &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/when-to-use-synthetic-vs-real-user-monitoring-performance&quot;&gt;when to use synthetic versus real user monitoring&lt;/a&gt;. Do not collapse &quot;the PageSpeed Insights score,&quot; &quot;Lighthouse,&quot; and &quot;Core Web Vitals&quot; into one sentence in a client deck.&lt;/p&gt;&lt;br&gt;
&lt;p&gt;&lt;strong&gt;Does Google use the Lighthouse Performance score as a ranking factor?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Google’s ranking systems use page experience signals tied to real-user Core Web Vitals concepts, not your lab Performance integer as a published ranking weight. Treat the score as an engineering and reporting aid. Use CrUX and Search Console for field status when data exists.&lt;/p&gt;&lt;br&gt;
&lt;p&gt;&lt;strong&gt;Why is Total Blocking Time in the score if INP is the Core Web Vital?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Lab runs need a synthetic interactivity signal during a single load. TBT fills that role inside the documented Lighthouse 10 Performance weights. INP is a field metric built from real interactions over a page life. Report both without merging them into one sentence.&lt;/p&gt;&lt;br&gt;
&lt;p&gt;&lt;strong&gt;Do Opportunities change the Performance score directly?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
No. Only metric scores feed the weighted average. Opportunities and Diagnostics guide fixes that may improve those metrics on the next run.&lt;/p&gt;&lt;br&gt;
&lt;p&gt;&lt;strong&gt;Why did desktop scores change a lot after older Lighthouse versions?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Before Lighthouse 6, desktop runs could be scored against mobile-derived curves and look artificially strong. From v6 onward, desktop has its own scoring. Compare desktop history carefully across that boundary.&lt;/p&gt;&lt;br&gt;
&lt;p&gt;&lt;strong&gt;Can Apogee Watcher show how each metric score was weighted for a run?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Watcher stores the PageSpeed Insights / Lighthouse results from scheduled tests for trends and budgets. For interactive weight exploration, use Google’s scoring calculator and Chrome’s scoring documentation alongside your Watcher history.&lt;/p&gt;&lt;br&gt;
&lt;h2 class=&quot;scroll-mt-24&quot;&gt;References&lt;/h2&gt;&lt;br&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://developer.chrome.com/docs/lighthouse/performance/performance-scoring&quot;&gt;Lighthouse performance scoring&lt;/a&gt; (Chrome for Developers)&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://googlechrome.github.io/lighthouse/scorecalc/&quot;&gt;Lighthouse scoring calculator&lt;/a&gt; (Chrome)&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://httparchive.org/&quot;&gt;HTTP Archive&lt;/a&gt; (scoring curve source data)&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/GoogleChrome/lighthouse/blob/main/docs/variability.md&quot;&gt;Lighthouse variability&lt;/a&gt; (Lighthouse project)&lt;/li&gt;
&lt;li&gt;&amp;lt;a href=&quot;https:
&lt;/li&gt;&lt;/ul&gt;</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/27089/google-lighthouse-score-explained-how-scoring-works</guid>
<pubDate>Mon, 14 Sep 2026 19:47:44 +0000</pubDate>
</item>
<item>
<title>How to increase PageSpeed/performance of a website that makes heavy use of interactive maps?</title>
<link>https://coderlegion.com/26199/how-to-increase-pagespeed-performance-of-website-that-makes-heavy-use-of-interactive-maps</link>
<description>&lt;p&gt;Defer map JavaScript until intent, reserve container height, and treat pan and zoom as INP work—not a one-time Lighthouse pass on a static screenshot.&lt;/p&gt;
&lt;p&gt;Store locators, delivery zones, property listings, and field-service dashboards often ship a full map widget above the fold because the business needs pins, polygons, and search on day one. PageSpeed Insights on that same URL frequently returns poor Largest Contentful Paint, high Interaction to Next Paint on pan and zoom, and Cumulative Layout Shift when the map canvas replaces a grey box. The gap is not “maps are bad”; it is that map SDKs behave like heavy third-party applications embedded inside a marketing page that Lighthouse still treats as a document.&lt;/p&gt;
&lt;p&gt;Below is a practical checklist for improving PageSpeed on map-heavy sites without removing the map. We use it when auditing client estates in &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/?utm_source=hashnode&amp;amp;utm_medium=referral&amp;amp;utm_campaign=hashnode-pagespeed-interactive-maps-performance&quot;&gt;Apogee Watcher&lt;/a&gt;; the same steps apply whether you run Google Maps, Mapbox, Leaflet, or a custom tile stack.&lt;/p&gt;
&lt;h3 id=&quot;why-do-interactive-maps-hurt-pagespeed-scores-more-than-static-images-&quot;&gt;Why do interactive maps hurt PageSpeed scores more than static images?&lt;/h3&gt;
&lt;p&gt;An interactive map is rarely one request. Typical embeds pull a large JavaScript bundle, WebGL or canvas rendering, vector or raster tiles, geocoding endpoints, and UI chrome (search, zoom controls, attribution). Lighthouse scores the initial navigation and a short interaction window. Maps pay for that work in three places at once:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Download and parse&lt;/strong&gt; of map JavaScript on the critical path.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Paint&lt;/strong&gt; of a large surface that often becomes the Largest Contentful Paint element.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Main-thread work&lt;/strong&gt; on drag, pinch, and zoom that shows up under Interaction to Next Paint long after First Contentful Paint looks acceptable.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Static map screenshots or server-rendered tiles can satisfy “show a location” without loading the full SDK on first paint. Interactive maps are justified when users must explore; the performance task is to keep that exploration off the path until they ask for it.&lt;/p&gt;
&lt;h3 id=&quot;which-core-web-vitals-break-first-on-map-heavy-pages-&quot;&gt;Which Core Web Vitals break first on map-heavy pages?&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;Metric &lt;/th&gt;&lt;th align=&quot;left&quot;&gt;What map embeds usually trigger &lt;/th&gt;&lt;th align=&quot;left&quot;&gt;What to check in lab&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Largest Contentful Paint (LCP)&lt;/strong&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Map canvas or hero tile layer becomes LCP; late SDK init delays paint &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Filmstrip: blank or grey box until SDK ready&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Interaction to Next Paint (INP)&lt;/strong&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Pan, zoom, drag handlers on main thread &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Trace interactions after load, not only idle metrics&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Cumulative Layout Shift (CLS)&lt;/strong&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Container without fixed height; controls injected above map &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Layout shift when map replaces placeholder&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;For a deeper read on INP mechanics, see &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/understanding-inp-newest-core-web-vital?utm_source=hashnode&amp;amp;utm_medium=referral&amp;amp;utm_campaign=hashnode-pagespeed-interactive-maps-performance&quot;&gt;Understanding INP: The Newest Core Web Vital and Why It Matters&lt;/a&gt;. For layout stability patterns beyond maps, see &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/cls-deep-dive-common-causes-fixes-layout-shift?utm_source=hashnode&amp;amp;utm_medium=referral&amp;amp;utm_campaign=hashnode-pagespeed-interactive-maps-performance&quot;&gt;CLS Deep-Dive: Common Causes and Fixes for Layout Shift&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;how-should-you-defer-map-javascript-until-the-user-shows-intent-&quot;&gt;How should you defer map JavaScript until the user shows intent?&lt;/h3&gt;
&lt;p&gt;The highest-leverage change on many sites is &lt;strong&gt;click-to-load&lt;/strong&gt; (sometimes called a facade):&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Render a static image, lightweight SVG outline, or low-zoom tile preview in the map container.&lt;/li&gt;
&lt;li&gt;Reserve the final width and height in CSS so nothing jumps when the real map mounts.&lt;/li&gt;
&lt;li&gt;Load the map SDK only after the user clicks “Show map”, taps the preview, or scrolls the map into view (if you use intersection-based loading, still keep a explicit affordance on mobile).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Async and defer attributes help script order, but they do not remove parse and execution cost from the first seconds after load. Intent gating moves that cost to the moment the user chooses interactivity. On listing pages with twenty pins, consider loading the map only on the detail view and keeping the index page on static previews.&lt;/p&gt;
&lt;h3 id=&quot;what-placeholder-and-container-rules-stop-layout-shift-&quot;&gt;What placeholder and container rules stop layout shift?&lt;/h3&gt;
&lt;p&gt;Map widgets often mount into a &lt;code&gt;div&lt;/code&gt; with &lt;code&gt;min-height: 400px&lt;/code&gt; that collapses before the SDK injects inner nodes. Fix the box before the SDK runs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Set &lt;strong&gt;explicit height&lt;/strong&gt; (or aspect ratio) on the map wrapper for each breakpoint.&lt;/li&gt;
&lt;li&gt;Preload a &lt;strong&gt;static preview&lt;/strong&gt; that matches the final aspect ratio.&lt;/li&gt;
&lt;li&gt;Avoid injecting toolbars or consent banners &lt;strong&gt;above&lt;/strong&gt; the map container after paint without reserved space.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If Lighthouse reports CLS on a map page, inspect whether the shift is the map itself or a late cookie banner pushing the canvas down. Both need reserved space; only one needs a deferred SDK.&lt;/p&gt;
&lt;h3 id=&quot;how-do-tile-weight-and-imagery-affect-largest-contentful-paint-&quot;&gt;How do tile weight and imagery affect Largest Contentful Paint?&lt;/h3&gt;
&lt;p&gt;Even when JavaScript is deferred, the first painted map surface may still be LCP if you load high-resolution raster tiles immediately. Mitigations that usually help:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Start at a &lt;strong&gt;lower zoom&lt;/strong&gt; or simplified basemap on first paint.&lt;/li&gt;
&lt;li&gt;Prefer &lt;strong&gt;vector tiles&lt;/strong&gt; where bandwidth and device allow; watch GPU cost on low-end phones.&lt;/li&gt;
&lt;li&gt;Do not treat the map as the hero on mobile unless the user task requires it; move search or copy above the fold and lazy-load the map below.&lt;/li&gt;
&lt;li&gt;Compress and size any &lt;strong&gt;static preview image&lt;/strong&gt; used as a facade; a 200 KB PNG preview defeats the purpose of deferring the SDK.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Compare mobile and desktop separately. A map that is below the fold on phone but full-width on desktop will have different LCP elements per strategy.&lt;/p&gt;
&lt;h3 id=&quot;why-do-pan-and-zoom-show-up-as-interaction-to-next-paint-problems-&quot;&gt;Why do pan and zoom show up as Interaction to Next Paint problems?&lt;/h3&gt;
&lt;p&gt;Lighthouse’s lab INP sample includes clicks, taps, and keyboard input during the measurement window. Map libraries attach move, drag, and wheel listeners that can keep the main thread busy. Mitigations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Throttle&lt;/strong&gt; redraw work during drag; avoid synchronous geocoding on every pixel move.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Offload&lt;/strong&gt; heavy geometry work to Web Workers where the SDK allows it.&lt;/li&gt;
&lt;li&gt;Reduce &lt;strong&gt; overlapping third-party tags&lt;/strong&gt; on the same page; map pages often also load analytics, chat, and consent stacks that compete for the same thread. Triage those scripts with the same discipline as any other heavy embed; see &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/third-party-scripts-performance-worst-offenders?utm_source=hashnode&amp;amp;utm_medium=referral&amp;amp;utm_campaign=hashnode-pagespeed-interactive-maps-performance&quot;&gt;Third-Party Scripts and Performance: How to Identify and Fix the Worst Offenders&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;One green lab run on a map page that nobody pans is not proof of good INP. Re-test with a short script: open the page, wait for idle, then pan and zoom before closing the trace.&lt;/p&gt;
&lt;h3 id=&quot;when-should-the-map-leave-the-critical-path-entirely-&quot;&gt;When should the map leave the critical path entirely?&lt;/h3&gt;
&lt;p&gt;Not every URL needs a live embed on first paint. Strong candidates for off-critical-path treatment:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Blog or editorial pages&lt;/strong&gt; with a single reference location (static map link or image is enough).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SEO landing pages&lt;/strong&gt; where the map supports trust but not conversion on first visit.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mobile homepages&lt;/strong&gt; where search and phone CTAs matter more than an interactive canvas.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Keep full interactivity on flows where the user task is explicitly spatial: “find nearest store”, “draw delivery zone”, “filter listings by map bounds”. Match embed weight to task frequency, not to what the design comp showed on day one.&lt;/p&gt;
&lt;h3 id=&quot;how-do-you-monitor-map-pages-after-you-ship-&quot;&gt;How do you monitor map pages after you ship?&lt;/h3&gt;
&lt;p&gt;Maps regress silently when marketing adds a tag, when the SDK auto-upgrades, or when tile CDN latency shifts by region. Treat map templates as &lt;strong&gt;first-class URLs&lt;/strong&gt; in monitoring, not as one-off homepage checks:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;List every template that mounts a map (store locator, listing detail, checkout zone picker).&lt;/li&gt;
&lt;li&gt;Run &lt;strong&gt;mobile and desktop&lt;/strong&gt; lab tests on a fixed URL set after each release.&lt;/li&gt;
&lt;li&gt;Compare &lt;strong&gt;LCP element&lt;/strong&gt; and &lt;strong&gt;INP&lt;/strong&gt; on interaction scripts, not only Performance score.&lt;/li&gt;
&lt;li&gt;Share &lt;code&gt;#summary&lt;/code&gt; links from domain reports when you audit a whole host with many location pages.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/how-to-set-up-automated-pagespeed-monitoring-for-multiple-sites?utm_source=hashnode&amp;amp;utm_medium=referral&amp;amp;utm_campaign=hashnode-pagespeed-interactive-maps-performance&quot;&gt;Automated PageSpeed monitoring&lt;/a&gt; catches drift when a plugin re-enables synchronous map loads on staging.&lt;/p&gt;
&lt;h3 id=&quot;faq-4&quot;&gt;FAQ&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Can I lazy-load a Google Maps iframe and still pass Core Web Vitals?&lt;/strong&gt;&lt;br&gt;
Often, if the iframe is not the LCP element and the placeholder reserves space. Iframes still fetch nested documents; combine lazy loading with a static preview and load on click for the best lab and field results.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Does replacing Google Maps with Mapbox automatically improve PageSpeed?&lt;/strong&gt;&lt;br&gt;
Not by itself. Any full SDK can dominate LCP and INP. Compare bundle weight, default tile behaviour, and how your integration mounts the canvas.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Will &lt;code&gt;async&lt;/code&gt; on the map script fix render-blocking warnings?&lt;/strong&gt;&lt;br&gt;
It helps script ordering but does not remove execution cost. Intent gating and smaller first paint surfaces usually move scores more than attribute tweaks alone.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Should the map be Largest Contentful Paint on a store locator page?&lt;/strong&gt;&lt;br&gt;
Sometimes yes. If the user’s job is “pick a store on the map”, optimise the map path rather than hiding it. If the job is “call this number”, promote copy and defer the embed.&lt;/p&gt;
&lt;h3 id=&quot;what-to-do-next-1&quot;&gt;What to do next&lt;/h3&gt;
&lt;p&gt;Pick one high-traffic map URL, run PageSpeed Insights on mobile, and note whether LCP, INP, or CLS fails first. Implement click-to-load with a fixed-height container, re-test with a pan-and-zoom interaction, then roll the pattern across templates. If you manage many client sites, add those URLs to a recurring monitoring set so the next plugin update does not restore synchronous map loads without notice.&lt;/p&gt;
&lt;h3 id=&quot;references-4&quot;&gt;References&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.corewebvitals.io/pagespeed/google-maps-100-percent-pagespeed&quot;&gt;Google Maps 100% page speed guide&lt;/a&gt; (Core Web Vitals.io)&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://developers.google.com/speed/docs/insights/BlockingJS&quot;&gt;Remove render-blocking JavaScript&lt;/a&gt; (Google PageSpeed Insights documentation)&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://web.dev/articles/vitals&quot;&gt;Web Vitals&lt;/a&gt; (web.dev)&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/third-party-scripts-performance-worst-offenders&quot;&gt;Third-Party Scripts and Performance: How to Identify and Fix the Worst Offenders&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/understanding-inp-newest-core-web-vital&quot;&gt;Understanding INP: The Newest Core Web Vital and Why It Matters&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/cls-deep-dive-common-causes-fixes-layout-shift&quot;&gt;CLS Deep-Dive: Common Causes and Fixes for Layout Shift&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/how-to-set-up-automated-pagespeed-monitoring-for-multiple-sites&quot;&gt;How to Set Up Automated PageSpeed Monitoring for Multiple Sites&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;Originally published on &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.hashnode.dev/pagespeed-interactive-maps-performance&quot;&gt;Hashnode&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/26199/how-to-increase-pagespeed-performance-of-website-that-makes-heavy-use-of-interactive-maps</guid>
<pubDate>Fri, 04 Sep 2026 10:21:46 +0000</pubDate>
</item>
<item>
<title>How we tuned apogee.lu for a 95 mobile PageSpeed score</title>
<link>https://coderlegion.com/25893/how-we-tuned-apogee-lu-for-a-95-mobile-pagespeed-score</link>
<description>&lt;p&gt;Render-blocking CSS, Cloudflare HTML rewrite, fixed hero heights, and Watcher domain report Summary before and after&lt;/p&gt;
&lt;p&gt;Our corporate site at &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogee.lu/&quot;&gt;apogee.lu&lt;/a&gt; is a static marketing front door: two HTML pages, a hero photograph, Victor Mono typography, and no application server in the path. It should be an easy Core Web Vitals win. Earlier this month, PageSpeed Insights on mobile still reported First Contentful Paint and Largest Contentful Paint above 2.5 seconds, with render-blocking CSS and a filmstrip that stayed blank until late in the load. We build &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/?utm_source=hashnode&amp;amp;utm_medium=referral&amp;amp;utm_campaign=hashnode-tuning-apogee-lu-pagespeed-mobile&quot;&gt;Apogee Watcher&lt;/a&gt; to monitor PageSpeed for client estates; tuning our own homepage was overdue, and we used the new domain-level report Summary to keep the work honest across every URL we ship under that host.&lt;/p&gt;
&lt;p&gt;Below is the sequence we ran: domain triage, diagnosis, failed experiments, and what landed us at &lt;strong&gt;95 mobile&lt;/strong&gt; and &lt;strong&gt;100 desktop&lt;/strong&gt; in lab tests, with &lt;strong&gt;Cumulative Layout Shift at 0&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&quot;what-pagespeed-insights-showed-before-we-changed-anything&quot;&gt;What PageSpeed Insights showed before we changed anything&lt;/h3&gt;
&lt;p&gt;Mobile lab runs told a consistent story. First Contentful Paint and Largest Contentful Paint were nearly equal, often around 2.6 to 3.0 seconds. The filmstrip showed no painted pixels for most of the timeline, then the full hero appeared in one step. Total Blocking Time stayed at zero; the bottleneck was not JavaScript on the main thread. Lighthouse flagged render-blocking &lt;code&gt;index.css&lt;/code&gt; from our asset CDN. Speed Index lagged because the visible hero arrived only after CSS allowed layout.&lt;/p&gt;
&lt;p&gt;That single-URL picture was useful, but incomplete. apogee.lu also ships &lt;code&gt;mailops.html&lt;/code&gt; and will keep growing small product pages. A green homepage with a neglected second URL is how agencies ship “we fixed PageSpeed” stories that fall apart on the next client call.&lt;/p&gt;
&lt;h3 id=&quot;how-we-used-watcher-domain-reports-before-touching-css&quot;&gt;How we used Watcher domain reports before touching CSS&lt;/h3&gt;
&lt;p&gt;Before we edited templates, we generated a &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/check?utm_source=hashnode&amp;amp;utm_medium=referral&amp;amp;utm_campaign=hashnode-tuning-apogee-lu-pagespeed-mobile&quot;&gt;domain report&lt;/a&gt; for the host and opened it on the &lt;strong&gt;Summary&lt;/strong&gt; tab. Shared domain reports now default to Summary: an &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/attention-free-score-domain-report-summary?utm_source=hashnode&amp;amp;utm_medium=referral&amp;amp;utm_campaign=hashnode-tuning-apogee-lu-pagespeed-mobile&quot;&gt;attention-free score&lt;/a&gt; (the share of completed mobile and desktop tests that pass Performance, category, and Core Web Vitals gates), a short list of metrics that still need attention, and the top pages that fail those gates. For apogee.lu that view made three decisions cheap: the homepage on &lt;strong&gt;mobile&lt;/strong&gt; was the first attention sink (LCP and render-blocking CSS), not a desktop-only quirk; &lt;code&gt;mailops.html&lt;/code&gt; either shared the same head and hero pattern or needed its own pass; and a shareable &lt;code&gt;#summary&lt;/code&gt; link kept the before state visible while we experimented locally. Single-URL PageSpeed Insights remains the right drill-down once Summary names the URL and strategy. Domain Summary is what stops you from optimising the wrong page first.&lt;/p&gt;
&lt;h3 id=&quot;how-we-found-the-real-largest-contentful-paint-bottleneck&quot;&gt;How we found the real Largest Contentful Paint bottleneck&lt;/h3&gt;
&lt;p&gt;Lighthouse named the hero photograph as the Largest Contentful Paint element, but the image was not the first gate. Our 500w WebP hero is about 15 KB and often finished downloading before layout. The gate was &lt;strong&gt;synchronous CSS&lt;/strong&gt;: the browser waited for stylesheet parse before painting.&lt;/p&gt;
&lt;p&gt;On production we also found Cloudflare injecting a &lt;code&gt;cdn-cgi/challenge-platform&lt;/code&gt; script into HTML. That script added main-thread work and pushed Largest Contentful Paint above 2.9 seconds. Setting &lt;code&gt;Cache-Control: no-transform&lt;/code&gt; on HTML from Apache stopped rewrite; injected scripts left view-source and lab Largest Contentful Paint dropped by roughly a second.&lt;/p&gt;
&lt;h3 id=&quot;moving-assets-to-our-cdn-and-reordering-the-document-head&quot;&gt;Moving assets to our CDN and reordering the document head&lt;/h3&gt;
&lt;p&gt;We moved images, CSS, JavaScript, and fonts to &lt;code&gt;https://cdn.apogee.lu/assets/&lt;/code&gt; with &lt;code&gt;preconnect&lt;/code&gt; in the head. Critical links now run before title and social meta so discovery order matches what lab filmstrips punish: CDN first, then paint-critical assets, then the rest of the document chrome.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;preconnect&lt;/code&gt; to the CDN&lt;/li&gt;
&lt;li&gt;Hero image &lt;code&gt;preload&lt;/code&gt; (500w on mobile via &lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Font preloads and &lt;code&gt;victor-mono.css&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Main CSS &lt;code&gt;preload&lt;/code&gt; and synchronous &lt;code&gt;stylesheet&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The hero download starts in the head even though paint still waits on CSS. That parallel fetch is why preload still helps Largest Contentful Paint when the stylesheet remains synchronous.&lt;/p&gt;
&lt;h3 id=&quot;hero-images-and-fixed-heights-per-breakpoint&quot;&gt;Hero images and fixed heights per breakpoint&lt;/h3&gt;
&lt;p&gt;We ship WebP at 500w, 780w, 1200w, and full width. &lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt; serves 500w on viewports up to 980px so mobile does not pull a 780w file on a 2x screen. The preload uses &lt;code&gt;media=&quot;(max-width: 980px)&quot;&lt;/code&gt; so lab mobile requests the smaller asset first.&lt;/p&gt;
&lt;p&gt;Fluid height caused Cumulative Layout Shift when we tried async CSS. &lt;code&gt;min-height: clamp(420px, 62vh, 720px)&lt;/code&gt; gave &lt;strong&gt;577px&lt;/strong&gt; on an iPhone 15 Pro Max (62% of 932px viewport height). Late full CSS shifted &lt;code&gt;.hero-stage&lt;/code&gt; and Lighthouse scored &lt;strong&gt;0.197&lt;/strong&gt; Cumulative Layout Shift.&lt;/p&gt;
&lt;p&gt;We replaced fluid height with fixed values from the same formula at canonical breakpoints:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Breakpoint &lt;/th&gt;&lt;th&gt;Reference viewport &lt;/th&gt;&lt;th&gt;Fixed height&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;≤980px     &lt;/td&gt;&lt;td&gt;390×844            &lt;/td&gt;&lt;td&gt;524px&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;981-1360px &lt;/td&gt;&lt;td&gt;1280×900           &lt;/td&gt;&lt;td&gt;558px&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;≥1361px    &lt;/td&gt;&lt;td&gt;design cap         &lt;/td&gt;&lt;td&gt;720px&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Mobile lab Cumulative Layout Shift returned to &lt;strong&gt;0&lt;/strong&gt; after deploy. That is the same “reserve space” idea you see in CLS how-tos, applied to a hero &lt;strong&gt;stage&lt;/strong&gt; whose height was CSS-driven rather than an &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; without dimensions. Width and height on the image alone would not have stopped the stage from resizing when late CSS replaced the fluid &lt;code&gt;min-height&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;css-and-fonts-what-we-tried-and-what-we-kept&quot;&gt;CSS and fonts: what we tried and what we kept&lt;/h3&gt;
&lt;p&gt;Extracting inline CSS into &lt;code&gt;index.css&lt;/code&gt; shrank HTML but did not remove render-blocking.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Inline critical CSS plus async full stylesheet&lt;/strong&gt; cut First Contentful Paint to about 1.0 seconds locally and cleared the render-blocking warning. It also broke typography (&lt;code&gt;font-display: optional&lt;/code&gt; skipped Victor Mono on slow links) and pushed Cumulative Layout Shift back up when below-the-fold rules arrived late. We kept &lt;strong&gt;synchronous main CSS&lt;/strong&gt; and &lt;strong&gt;self-hosted Victor Mono&lt;/strong&gt; on the CDN instead: four latin WOFF2 files and a small &lt;code&gt;@font-face&lt;/code&gt; sheet, with preloads for normal and italic latin, and &lt;code&gt;font-display: swap&lt;/code&gt; so the correct family appears after files load. The Lighthouse render-blocking warning can remain while Performance still lands in the mid-90s; we preferred stable layout and brand fonts over chasing a green Opportunities row.&lt;/p&gt;
&lt;h3 id=&quot;scores-after-deploy-and-what-summary-showed-next&quot;&gt;Scores after deploy and what Summary showed next&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://apogeewatcher.com/blog-images/44-apogee-lu-pagespeed-mobile-desktop.png&quot; alt=&quot;PageSpeed Insights for apogee.lu after deploy: mobile Performance 95 and desktop Performance 100 side by side&quot;&gt;&lt;/p&gt;
&lt;p&gt;Mobile PageSpeed Insights after CDN alignment (captured &lt;strong&gt;30 Aug 2026&lt;/strong&gt;):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Performance 95&lt;/strong&gt;  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;First Contentful Paint ~1.7s&lt;/strong&gt;, &lt;strong&gt;Largest Contentful Paint ~2.4s&lt;/strong&gt;  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cumulative Layout Shift 0&lt;/strong&gt;, &lt;strong&gt;Total Blocking Time 0ms&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Desktop lab reached &lt;strong&gt;100&lt;/strong&gt; with sub-second paint metrics (FCP &lt;strong&gt;0.5s&lt;/strong&gt;, LCP &lt;strong&gt;0.6s&lt;/strong&gt;, Speed Index &lt;strong&gt;0.7s&lt;/strong&gt;). Speed Index on mobile can stay above 4 seconds because the hero image paints after text; we accept that on a rarely changed marketing page rather than reopening the async-CSS experiment.&lt;/p&gt;
&lt;p&gt;We regenerated the domain report and opened Summary again. All &lt;strong&gt;4&lt;/strong&gt; completed page tests passed the CWV and category gates, so the attention-free score sat at &lt;strong&gt;100%&lt;/strong&gt;, with average Lighthouse Performance &lt;strong&gt;97&lt;/strong&gt; on mobile and &lt;strong&gt;100&lt;/strong&gt; on desktop.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://apogeewatcher.com/blog-images/44-apogee-lu-domain-report-summary.png&quot; alt=&quot;Apogee Watcher domain report Summary for apogee.lu: site status PASS, attention-free score 100%, four completed page tests within gates&quot;&gt;&lt;/p&gt;
&lt;p&gt;That before/after pair is what we keep when someone asks whether the ship actually moved the portfolio, not only one PageSpeed Insights screenshot.&lt;/p&gt;
&lt;h3 id=&quot;what-we-monitor-now&quot;&gt;What we monitor now&lt;/h3&gt;
&lt;p&gt;We keep &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogee.lu/&quot;&gt;apogee.lu&lt;/a&gt; on scheduled PageSpeed runs in Watcher and re-check after HTML header, Cloudflare, or CDN cache changes. Lab green after deploy proves the fix shipped. Search Console field data still moves on its &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/why-core-web-vitals-fix-not-in-crux-yet-28-day-window?utm_source=hashnode&amp;amp;utm_medium=referral&amp;amp;utm_campaign=hashnode-tuning-apogee-lu-pagespeed-mobile&quot;&gt;28-day CrUX window&lt;/a&gt;, so we do not treat one green lab week as field proof.&lt;/p&gt;
&lt;p&gt;Manual PageSpeed Insights before every deploy does not scale across client sites. &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/sign-up?utm_source=hashnode&amp;amp;utm_medium=referral&amp;amp;utm_campaign=hashnode-tuning-apogee-lu-pagespeed-mobile&quot;&gt;Apogee Watcher&lt;/a&gt; automates runs, stores history, and alerts on regression. Domain reports with Summary give you the same triage shape we used on our own host. For pipeline versus scheduled monitoring, see &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/lighthouse-ci-vs-managed-monitoring-build-vs-buy-agencies?utm_source=hashnode&amp;amp;utm_medium=referral&amp;amp;utm_campaign=hashnode-tuning-apogee-lu-pagespeed-mobile&quot;&gt;Lighthouse CI vs managed monitoring&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;faq-5&quot;&gt;FAQ&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Does CDN CSS stop render-blocking?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;No. Synchronous &lt;code&gt;stylesheet&lt;/code&gt; blocks first paint until parsed, even for a small file. Preload helps discovery; async or inlined critical CSS removes the gate. We used sync CSS plus fixed hero height to hold Cumulative Layout Shift at zero.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why preload the hero if CSS blocks paint?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The image can download in parallel with the stylesheet. When paint is allowed, Largest Contentful Paint is shorter if those bytes are already cached instead of starting only after CSS finishes.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why open a domain report instead of only PageSpeed Insights?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;PageSpeed Insights answers one URL. Domain Summary answers which URLs and strategies still need attention under one host, with an attention-free pass rate you can share. Drill into Opportunities after Summary names the page.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Next step:&lt;/strong&gt; Run PageSpeed Insights on your homepage. If First Contentful Paint equals Largest Contentful Paint in the filmstrip, check render-blocking CSS and injected scripts before resizing images. Generate a &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/check?utm_source=hashnode&amp;amp;utm_medium=referral&amp;amp;utm_campaign=hashnode-tuning-apogee-lu-pagespeed-mobile&quot;&gt;free domain scan&lt;/a&gt;, open &lt;code&gt;#summary&lt;/code&gt;, then &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/sign-up?utm_source=hashnode&amp;amp;utm_medium=referral&amp;amp;utm_campaign=hashnode-tuning-apogee-lu-pagespeed-mobile&quot;&gt;start a Watcher trial&lt;/a&gt; to keep the same URLs on a schedule.&lt;/p&gt;
&lt;h3 id=&quot;references-5&quot;&gt;References&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://pagespeed.web.dev/&quot;&gt;PageSpeed Insights&lt;/a&gt; (Google)&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://web.dev/articles/optimize-lcp&quot;&gt;Optimize Largest Contentful Paint&lt;/a&gt; (web.dev)&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://developer.chrome.com/docs/lighthouse/performance/render-blocking-resources&quot;&gt;Render-blocking resources&lt;/a&gt; (Chrome Developers)&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://developers.google.com/speed/docs/insights/OptimizeCSSDelivery&quot;&gt;Optimize CSS Delivery&lt;/a&gt; (Google)&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/attention-free-score-domain-report-summary&quot;&gt;Attention-Free Score: How Domain Reports Show Which Pages Need Work&lt;/a&gt; (Apogee Watcher)&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/why-core-web-vitals-fix-not-in-crux-yet-28-day-window&quot;&gt;Why a Core Web Vitals fix may not show in CrUX yet&lt;/a&gt; (Apogee Watcher)&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/lighthouse-ci-vs-managed-monitoring-build-vs-buy-agencies&quot;&gt;Lighthouse CI vs managed monitoring for agencies&lt;/a&gt; (Apogee Watcher)&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://apogee.lu/&quot;&gt;Apogee Information Systems&lt;/a&gt; (corporate site)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;Originally published on &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.hashnode.dev/tuning-apogee-lu-pagespeed-mobile-score&quot;&gt;Hashnode&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/25893/how-we-tuned-apogee-lu-for-a-95-mobile-pagespeed-score</guid>
<pubDate>Mon, 31 Aug 2026 05:39:06 +0000</pubDate>
</item>
<item>
<title>How Lighthouse Performance Scores Are Recorded and Calculated</title>
<link>https://coderlegion.com/24757/how-lighthouse-performance-scores-are-recorded-and-calculated</link>
<description>&lt;p&gt;A client forwards a PageSpeed Insights screenshot with a big green 94 and asks whether the site is “fast enough for Google.” Another week the same URL shows 81 on mobile after a tag manager change, and the account thread fills with theories. Both reactions treat the Lighthouse Performance score as a single truth. It is not. It is a lab construct: metrics recorded under controlled conditions, then calculated into a 0–100 number with curves and weights that Google documents and occasionally revises.&lt;/p&gt;&lt;p&gt;Chrome’s &lt;a rel=&quot;nofollow&quot; href=&quot;https://developer.chrome.com/docs/lighthouse/performance/performance-scoring&quot;&gt;Lighthouse performance scoring&lt;/a&gt; guide is the source of truth for that math. What follows translates it for agency reporting: what gets recorded in a run, how the score is calculated, which weights apply in current Lighthouse 10 documentation, why the number is not the same as field Core Web Vitals, and how Apogee Watcher stores category scores from scheduled runs without pretending they are CrUX. Keep the calculator open while you read if you want to poke individual metrics.&lt;/p&gt;&lt;h2 class=&quot;scroll-mt-24&quot;&gt;What a Lighthouse Performance score actually is&lt;/h2&gt;&lt;p&gt;The Performance score is a single 0–100 summary for one lab run of one URL under one device strategy (mobile or desktop). It is not a ranking factor by itself. It is not a rolling average of real visitors. Opportunities and Diagnostics in the report do not add points directly; they explain ways the underlying metrics might improve, which can raise the score indirectly when those metrics move.&lt;/p&gt;&lt;p&gt;Colour bands in the docs are simple: 0–49 poor (red), 50–89 needs improvement (orange), 90–100 good (green). A perfect 100 is unusually hard. Moving from 99 to 100 can need as much metric improvement as moving from 90 to 94. For client language, “good” means a lab run that cleared 90 under that profile, not that every user on every network had a green experience.&lt;/p&gt;&lt;p&gt;PageSpeed Insights uses Lighthouse for the lab block. When people say “the PageSpeed Insights score,” they usually mean that lab Performance category, sometimes while looking at a CrUX field panel on the same screen. Keep those two stories separate in every deck.&lt;/p&gt;&lt;h2 class=&quot;scroll-mt-24&quot;&gt;How Lighthouse records lab metrics in a controlled run&lt;/h2&gt;&lt;p&gt;Recording comes first. Lighthouse (and PageSpeed Insights lab mode) loads the URL in a controlled environment: a chosen form factor, simulated network and CPU throttling for typical mobile profiles, and a single navigation. During that load it measures timings and layout behaviour. Common Performance metrics include First Contentful Paint (FCP), Speed Index (SI), Largest Contentful Paint (LCP), Total Blocking Time (TBT), and Cumulative Layout Shift (CLS). Diagnostics such as Time to First Byte (TTFB) may appear as supporting detail. None of those values are taken from real visitors in that run.&lt;/p&gt;&lt;p&gt;The lab profile matters. Mobile and desktop use different throttling and, since Lighthouse 6, different scoring curves so desktop is not scored on mobile HTTP Archive distributions. Running on a quiet office machine with extensions disabled still differs from a busy shared CI worker. Chrome documents common causes of score fluctuation: ads and A/B tests, routing changes, device power, extensions, antivirus. Treat a single paste as a sample from a distribution, not as the only possible score for that URL.&lt;/p&gt;&lt;p&gt;Scheduled monitoring reduces the “two screenshots, no baseline” problem. You still measure lab conditions, but you compare like with like over time. That is the operational gap we described in &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/pagespeed-insights-vs-automated-monitoring-when-manual-checks-arent-enough&quot;&gt;PageSpeed Insights versus automated monitoring&lt;/a&gt;.&lt;/p&gt;&lt;h2 class=&quot;scroll-mt-24&quot;&gt;How Lighthouse calculates the 0–100 Performance score&lt;/h2&gt;&lt;p&gt;Calculation is a second step. Lighthouse does not average raw milliseconds into one number. For each metric it maps the recorded value onto a 0–100 metric score using a log-normal scoring curve calibrated from HTTP Archive site data. Those metric scores stay under the hood in the usual report UI. The visible Performance score is then a weighted average of the metric scores.&lt;/p&gt;&lt;p&gt;Chrome describes the curve control points clearly. The 25th percentile of HTTP Archive data for a metric maps to a metric score of 50. The 8th percentile maps to 90 (the “good” control point). Between roughly 0.50 and 0.92 the relationship is nearly linear; near 0.96 returns diminish and further metric gains buy less score. Exploring a metric in the &lt;a rel=&quot;nofollow&quot; href=&quot;https://googlechrome.github.io/lighthouse/scorecalc/&quot;&gt;Lighthouse scoring calculator&lt;/a&gt; is the fastest way to see how a raw LCP or TBT value becomes a metric score before weights apply.&lt;/p&gt;&lt;p&gt;Because the curves come from real-site distributions, “good” is relative to the web as captured in HTTP Archive, not to an arbitrary round number your client invented in a brand guideline. When Lighthouse major versions change weights or curves, historical scores need a footnote. Always cite the Lighthouse version your tool used when you compare quarters.&lt;/p&gt;&lt;h2 class=&quot;scroll-mt-24&quot;&gt;Lighthouse scoring weights (Lighthouse 10)&lt;/h2&gt;&lt;p&gt;Chrome’s documented &lt;strong&gt;Lighthouse 10&lt;/strong&gt; weights for the Performance score are:&lt;/p&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th&gt;Metric&lt;/th&gt;&lt;th&gt;Weight&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;First Contentful Paint (FCP)&lt;/td&gt;&lt;td&gt;10%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Speed Index (SI)&lt;/td&gt;&lt;td&gt;10%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Largest Contentful Paint (LCP)&lt;/td&gt;&lt;td&gt;25%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Total Blocking Time (TBT)&lt;/td&gt;&lt;td&gt;30%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Cumulative Layout Shift (CLS)&lt;/td&gt;&lt;td&gt;25%&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;TBT carries the largest single weight. LCP and CLS share 25% each. FCP and Speed Index are lighter. Earlier majors differed; Lighthouse 8 still weighted Time to Interactive and used a different CLS weight. Verify the table for the version you ship in CI or see in PageSpeed Insights, and re-check the calculator when Google publishes a new major.&lt;/p&gt;&lt;p&gt;INP may appear in field tooling and in some report contexts, but the lab Performance blend documented for Lighthouse 10 emphasises &lt;strong&gt;TBT&lt;/strong&gt; as the interactivity proxy inside the score. Do not tell a client that “INP is 30% of the Lighthouse score.” Point them at TBT for lab scoring and at field INP for CrUX and Search Console when samples exist. Metric definitions live in &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/lcp-inp-cls-what-each-core-web-vital-means-and-how-to-fix-it&quot;&gt;LCP, INP, and CLS explained&lt;/a&gt;; field interactivity detail is in our &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/understanding-inp-newest-core-web-vital&quot;&gt;INP guide&lt;/a&gt;.&lt;/p&gt;&lt;h2 class=&quot;scroll-mt-24&quot;&gt;Why the Performance score is not the same as Core Web Vitals field data&lt;/h2&gt;&lt;p&gt;Field Core Web Vitals come from real Chrome users in the Chrome User Experience Report (CrUX), with Search Console and the PageSpeed Insights field section as common surfaces. Lab Performance scores come from one synthetic navigation. Both can mention LCP and CLS; only the lab score folds in Speed Index and TBT with the weights above. Field INP has no twin inside that Lighthouse 10 weight table.&lt;/p&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th&gt;Question&lt;/th&gt;&lt;th&gt;Lab Performance score&lt;/th&gt;&lt;th&gt;Field Core Web Vitals (CrUX)&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Who was measured?&lt;/td&gt;&lt;td&gt;Controlled lab profile&lt;/td&gt;&lt;td&gt;Real Chrome users (sample)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;What number?&lt;/td&gt;&lt;td&gt;Weighted 0–100 from metric scores&lt;/td&gt;&lt;td&gt;Percentiles for LCP, INP, CLS (and related)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Interactivity in the blend?&lt;/td&gt;&lt;td&gt;TBT (lab)&lt;/td&gt;&lt;td&gt;INP (field)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Good enough for SEO field status?&lt;/td&gt;&lt;td&gt;No, not by itself&lt;/td&gt;&lt;td&gt;Search Console / CrUX when eligible&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Useful after a deploy?&lt;/td&gt;&lt;td&gt;Yes, fast regression signal&lt;/td&gt;&lt;td&gt;Yes, after the rolling window catches up&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;Agencies need both clocks. Lab catches “we broke the template today.” Field answers “Chrome users over ~28 days still feel it.” We covered the field lag in &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/why-core-web-vitals-fix-not-in-crux-yet-28-day-window&quot;&gt;Why your Core Web Vitals fix is not in CrUX yet&lt;/a&gt; and the synthetic versus RUM split in &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/when-to-use-synthetic-vs-real-user-monitoring-performance&quot;&gt;When to use synthetic versus real user monitoring&lt;/a&gt;. Missing field rows are a sampling problem, not proof the lab score is wrong; see &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/pagespeed-insights-no-cls-inp-for-url&quot;&gt;When PageSpeed Insights shows no CLS or INP&lt;/a&gt;.&lt;/p&gt;&lt;h2 class=&quot;scroll-mt-24&quot;&gt;Why Lighthouse scores fluctuate between runs&lt;/h2&gt;&lt;p&gt;Variability is normal. The same URL can move several points between back-to-back runs when ads, consent banners, third-party scripts, or CPU contention differ. Chrome’s variability documentation exists for a reason. For retainers, prefer medians or repeated scheduled runs over a single heroic screenshot. Agree the device strategy (mobile versus desktop) before you argue about a five-point swing.&lt;/p&gt;&lt;p&gt;CI and local DevTools can also disagree because of Lighthouse version, throttling presets, and whether the environment matches PageSpeed Insights. When you automate audits with coding agents or DevTools workflows, still treat the Performance number as lab math under a stated version. Our note on &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/lighthouse-audits-ai-agents-chrome-devtools&quot;&gt;Lighthouse audits with AI agents&lt;/a&gt; covers the agency gap between one-off agent runs and portfolio schedules. Separate audits such as Baseline Features change Best Practices diagnostics without rewriting the Performance weight table; see &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/lighthouse-baseline-features-audit&quot;&gt;Lighthouse’s Baseline Features audit&lt;/a&gt;.&lt;/p&gt;&lt;h2 class=&quot;scroll-mt-24&quot;&gt;How agencies should report Lighthouse scores to clients&lt;/h2&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Name the artefact:&lt;/strong&gt; “Lighthouse / PageSpeed Insights lab Performance score,” not “Google’s speed ranking.”&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;State device and version:&lt;/strong&gt; mobile or desktop, and Lighthouse major when known.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Show the drivers:&lt;/strong&gt; LCP, TBT, and CLS usually explain most of the blend under current weights.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Separate field status:&lt;/strong&gt; CrUX / Search Console on their own slide or paragraph.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use trends:&lt;/strong&gt; three or more scheduled runs beat one paste after a deploy.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Open the calculator&lt;/strong&gt; when a stakeholder wants to know how many milliseconds buy the next ten points.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Avoid score chasing at 99–100&lt;/strong&gt; unless the contract truly requires vanity greens; spend engineering time on user-visible LCP and TBT first.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Budgets work better on metric thresholds than on a single Performance integer, because the integer hides which metric moved. Pair score trends with LCP and TBT budgets on money URLs so engineering knows what to fix. A five-point score drop that is all TBT is a different ticket from one that is all CLS.&lt;/p&gt;&lt;h2 class=&quot;scroll-mt-24&quot;&gt;Where Apogee Watcher stores Performance scores&lt;/h2&gt;&lt;p&gt;Apogee Watcher schedules PageSpeed Insights tests across multi-tenant portfolios and stores the lab category scores and metric payloads from those runs for trends, budgets, and alerts. That history is lab data under Google’s PSI/Lighthouse pipeline. It is not a substitute for CrUX percentiles, and it does not claim to weight INP inside the Performance blend.&lt;/p&gt;&lt;p&gt;Use Watcher when you need the same URLs retested on a cadence after deploys, with mobile and desktop strategies and client-ready charts. Use CrUX and Search Console for field Core Web Vitals when samples exist. Use the scoring calculator when someone asks how the 0–100 number is built. Layer the tools; do not collapse them into one green circle in a slide.&lt;/p&gt;&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/sign-up&quot;&gt;Start a free trial&lt;/a&gt; to schedule PageSpeed tests and keep Performance score trends beside metric budgets. Or &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/check&quot;&gt;run a free PageSpeed check&lt;/a&gt; on a priority URL and open the &lt;a rel=&quot;nofollow&quot; href=&quot;https://googlechrome.github.io/lighthouse/scorecalc/&quot;&gt;Lighthouse scoring calculator&lt;/a&gt; beside the result.&lt;/p&gt;&lt;h2 class=&quot;scroll-mt-24&quot;&gt;FAQ&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Does Google use the Lighthouse Performance score as a ranking factor?&lt;/strong&gt;&lt;br&gt;Google’s ranking systems use page experience signals tied to real-user Core Web Vitals concepts, not your lab Performance integer as a published ranking weight. Treat the score as an engineering and reporting aid. Use CrUX and Search Console for field status when data exists.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Why is Total Blocking Time in the score if INP is the Core Web Vital?&lt;/strong&gt;&lt;br&gt;Lab runs need a synthetic interactivity signal during a single load. TBT fills that role inside the documented Lighthouse 10 Performance weights. INP is a field metric built from real interactions over a page life. Report both without merging them into one sentence.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Do Opportunities change the Performance score directly?&lt;/strong&gt;&lt;br&gt;No. Only metric scores feed the weighted average. Opportunities and Diagnostics guide fixes that may improve those metrics on the next run.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Why did desktop scores change a lot after older Lighthouse versions?&lt;/strong&gt;&lt;br&gt;Before Lighthouse 6, desktop runs could be scored against mobile-derived curves and look artificially strong. From v6 onward, desktop has its own scoring. Compare desktop history carefully across that boundary.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Can Apogee Watcher show how each metric score was weighted for a run?&lt;/strong&gt;&lt;br&gt;Watcher stores the PageSpeed Insights / Lighthouse results from scheduled tests for trends and budgets. For interactive weight exploration, use Google’s scoring calculator and Chrome’s scoring documentation alongside your Watcher history.&lt;/p&gt;&lt;h2 class=&quot;scroll-mt-24&quot;&gt;References&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://developer.chrome.com/docs/lighthouse/performance/performance-scoring&quot;&gt;Lighthouse performance scoring&lt;/a&gt; (Chrome for Developers)&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://googlechrome.github.io/lighthouse/scorecalc/&quot;&gt;Lighthouse scoring calculator&lt;/a&gt; (Chrome)&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://httparchive.org/&quot;&gt;HTTP Archive&lt;/a&gt; (scoring curve source data)&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/GoogleChrome/lighthouse/blob/main/docs/variability.md&quot;&gt;Lighthouse variability&lt;/a&gt; (Lighthouse project)&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/lcp-inp-cls-what-each-core-web-vital-means-and-how-to-fix-it&quot;&gt;LCP, INP, CLS: What Each Core Web Vital Means and How to Fix It&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/understanding-inp-newest-core-web-vital&quot;&gt;Understanding INP: The Newest Core Web Vital and Why It Matters&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/pagespeed-insights-vs-automated-monitoring-when-manual-checks-arent-enough&quot;&gt;PageSpeed Insights vs Automated Monitoring&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/when-to-use-synthetic-vs-real-user-monitoring-performance&quot;&gt;When to Use Synthetic vs Real User Monitoring for Performance&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/why-core-web-vitals-fix-not-in-crux-yet-28-day-window&quot;&gt;Why Your Core Web Vitals Fix Isn't in CrUX Yet (28-Day Window)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/pagespeed-insights-no-cls-inp-for-url&quot;&gt;When PageSpeed Insights Shows No CLS or INP for Your URL&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/lighthouse-audits-ai-agents-chrome-devtools&quot;&gt;Automate Lighthouse Audits with AI Agents&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/lighthouse-baseline-features-audit&quot;&gt;Lighthouse’s New Baseline Features Audit&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/24757/how-lighthouse-performance-scores-are-recorded-and-calculated</guid>
<pubDate>Tue, 18 Aug 2026 09:44:00 +0000</pubDate>
</item>
<item>
<title>Automate Lighthouse Audits with AI Agents: What Chrome DevTools Means for Agencies</title>
<link>https://coderlegion.com/23585/automate-lighthouse-audits-with-ai-agents-what-chrome-devtools-means-for-agencies</link>
<description>&lt;p&gt;Chrome has documented how coding agents can run &lt;a rel=&quot;nofollow&quot; href=&quot;https://developer.chrome.com/docs/devtools/agents/use-cases/lighthouse-audit&quot;&gt;Lighthouse audits inside Chrome DevTools for agents&lt;/a&gt;. Instead of grepping a repository for vague performance clues, the agent loads the page you care about and measures accessibility, SEO, best practices, and agentic browsing against live runtime behaviour. That loop is better for fixing a checkout UI on a local server than another round of static guessing from file names alone.&lt;/p&gt;&lt;p&gt;Agencies should treat this as a development tool, not a finished monitoring programme. A Lighthouse AI agent can catch colour contrast failures or missing meta tags while a developer still has the branch open. It does not replace scheduled tests across forty client sites, budget thresholds, or alerts when a theme deploy regresses Largest Contentful Paint overnight. The sections below separate what Chrome’s agent workflow does well from what multi-tenant PageSpeed monitoring still has to own.&lt;/p&gt;&lt;h2 id=&quot;what-a-lighthouse-ai-agent-measures-in-chrome-devtools&quot; class=&quot;scroll-mt-24&quot;&gt;What a Lighthouse AI agent measures in Chrome DevTools&lt;/h2&gt;&lt;p&gt;Chrome’s documentation groups agent-driven Lighthouse work into four categories. Accessibility covers screen-reader readiness and related checks such as contrast and ARIA labelling. SEO covers technical discoverability signals search engines need to find and understand the page. Best practices covers modern web hygiene: HTTPS usage, console errors, deprecated APIs, and similar technical standards. Agentic browsing covers how far AI assistants can understand and interact with the site, which sits beside Core Web Vitals work rather than replacing it.&lt;/p&gt;&lt;p&gt;The useful claim is runtime evidence. The agent is not inventing a checklist from file names. It triggers Lighthouse against a page that is actually visible in Chrome, including local development servers and HTML opened through the &lt;code&gt;file://&lt;/code&gt; protocol. Staging URLs count the same way. A coding agent can verify a UI change on &lt;code&gt;localhost&lt;/code&gt; before anyone merges, which is where agencies often lose days when accessibility and technical SEO fail only after client UAT.&lt;/p&gt;&lt;h3&gt;Local, staging, and file:// support for Chrome DevTools agents&lt;/h3&gt;&lt;p&gt;Chrome states that the agent can audit any page visible in the browser. That includes local development servers and local HTML files. For agency teams, that means you can run a Lighthouse AI agent against a feature branch without waiting for a public staging hostname. Keep authentication and feature flags in mind: a logged-in staging route can look healthy while the anonymous production path still fails SEO or accessibility checks.&lt;/p&gt;&lt;p&gt;Chrome also warns about browser behaviour during audits. The page may resize or reload while Lighthouse simulates different devices. Anyone pairing an agent with a shared staging tab should expect brief disruption. Treat agent audits as intentional lab sessions, not something you leave running on a client demo screen without warning.&lt;/p&gt;&lt;h2 id=&quot;prompts-for-a-lighthouse-ai-agent-accessibility-seo-and-best-practices&quot; class=&quot;scroll-mt-24&quot;&gt;Prompts for a Lighthouse AI agent: accessibility, SEO, and best practices&lt;/h2&gt;&lt;p&gt;Chrome’s examples are short enough to paste into a coding agent that already has DevTools agent tooling. They map cleanly to delivery habits agencies already use. Keep the prompt, the failing audits, and the re-run result in the ticket so the fix is reviewable after the chat window closes.&lt;/p&gt;&lt;h3&gt;How to improve accessibility with a Lighthouse AI agent&lt;/h3&gt;&lt;p&gt;Prompt: “How can I improve accessibility on this page as measured by Lighthouse?” The documented behaviour is a mobile &lt;code&gt;formFactor&lt;/code&gt; audit that surfaces issues such as insufficient colour contrast or missing ARIA labels, then proposes concrete code fixes. That pass earns its keep when a designer ships a new badge colour that still looks fine to sighted reviewers on a calibrated monitor. Ask for the failing audit IDs in the pull request so review does not depend on chat history alone.&lt;/p&gt;&lt;h3&gt;How to catch technical SEO blockers before launch&lt;/h3&gt;&lt;p&gt;Prompt: “According to Lighthouse audit, how can I improve this page for better discoverability in search?” The agent looks for missing meta tags, canonical links, or weak descriptive text and can offer source updates. Catching those blockers in staging is cheaper than explaining a soft indexing story after launch. Pair the audit with the templates that matter commercially (product, pricing, checkout), not only the marketing homepage the agent happens to have open.&lt;/p&gt;&lt;h3&gt;How to validate best practices on local and staging&lt;/h3&gt;&lt;p&gt;Prompt: “Does my site follow best practices as measured by Lighthouse?” The audit reviews HTTPS, console errors, and deprecated API calls. Agencies often skip this pass because the design looks finished. Console noise and mixed content still show up in client QA and burn trust in the report pack.&lt;/p&gt;&lt;h3&gt;When to run a full mobile and desktop Lighthouse audit&lt;/h3&gt;&lt;p&gt;Prompt: “Run a full Lighthouse audit of my site, in mobile and desktop, and suggest improvement areas and possible fixes for any problems you find.” Chrome notes that agents with source context may suggest code fixes, and agents with broader context may also suggest server or backend configuration changes. Treat backend suggestions as hypotheses for your platform team, not as automatic production changes. Re-run after the patch so the conversation ends on measured results, not on a single hopeful pass.&lt;/p&gt;&lt;p&gt;None of these prompts invents a new quality bar. They attach an existing Lighthouse run to the agent’s conversation so the next patch is grounded in failing audits rather than guesswork. If the agent cannot see the page in Chrome, fix the browser connection first; no prompt compensates for an empty viewport.&lt;/p&gt;&lt;h2 id=&quot;lighthouse-agentic-browsing-versus-core-web-vitals-reporting&quot; class=&quot;scroll-mt-24&quot;&gt;Lighthouse agentic browsing versus Core Web Vitals reporting&lt;/h2&gt;&lt;p&gt;Agentic browsing is the category that often confuses stakeholders. It is not another 0–100 Performance score. It asks whether assistants can understand and interact with the page: tool registration patterns such as WebMCP, agent-oriented accessibility, layout stability that affects programmatic clicks, and related discoverability signals. We already covered how experimental Lighthouse agentic browsing scoring works, including fractional pass ratios and WebMCP observation, in &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/lighthouse-agentic-browsing-scoring&quot;&gt;Lighthouse Agentic Browsing: How to rank in chatbots&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;For agencies, the operational rule is simple. Keep Core Web Vitals and PageSpeed Performance scores as the client-facing performance language you already report. Use agentic browsing audits as an early research signal when a product site exposes agent tools or when a client asks whether AI assistants can use their flows. Do not promote experimental pass ratios into a retainer KPI until the standard and your tooling story are stable. Chrome’s agent docs put agentic browsing in the same Lighthouse family as accessibility and SEO, which is correct for developers, but buyers still buy predictability on Largest Contentful Paint, Interaction to Next Paint, and Cumulative Layout Shift first.&lt;/p&gt;&lt;p&gt;If you need the math behind how Lighthouse turns raw timings into a Performance category score, Chrome documents the scoring model, and we have a dedicated Watcher explainer scheduled for that calculation path. The agency takeaway for agent workflows is narrower: a coding agent can improve category scores by fixing the failed audits it sees, but those lab scores are still synthetic. Field Core Web Vitals remain a separate truth.&lt;/p&gt;&lt;h2 id=&quot;why-one-ai-coding-agent-lighthouse-run-is-not-portfolio-monitoring&quot; class=&quot;scroll-mt-24&quot;&gt;Why one AI coding agent Lighthouse run is not portfolio monitoring&lt;/h2&gt;&lt;p&gt;A successful agent session looks like this: open the priority URL on staging, run accessibility and SEO audits, apply fixes, re-run, then merge when the failures that blocked the ticket are cleared. That loop is useful. It is also a single device, a single URL, a single moment in time, and usually a single human watching the tab.&lt;/p&gt;&lt;p&gt;Agency failure modes live elsewhere. A plugin update lands on Friday across twelve WordPress sites. A Shopify theme ships a new app block that only hurts mobile Interaction to Next Paint on product templates. A marketing team adds a tag manager container that never appears on the developer’s &lt;code&gt;localhost&lt;/code&gt; build. Spot PageSpeed Insights runs and agent audits both miss that class of regression unless someone remembers to re-check every affected URL after every change. We unpacked when manual checks stop scaling in &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/pagespeed-insights-vs-automated-monitoring-when-manual-checks-arent-enough&quot;&gt;PageSpeed Insights vs Automated Monitoring: When Manual Checks Aren't Enough&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Synthetic versus field data adds another split. Agent-driven Lighthouse is synthetic lab evidence, closer to a controlled PageSpeed Insights run than to Chrome UX Report percentiles. Knowing when to lean on lab schedules versus real-user monitoring is a separate decision; see &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/when-to-use-synthetic-vs-real-user-monitoring-performance&quot;&gt;When to Use Synthetic vs Real User Monitoring for Performance&lt;/a&gt;. Use the agent to fix what is broken in the environment you control, then keep scheduled synthetic tests on production priority URLs so regressions after merge still raise an alert.&lt;/p&gt;&lt;h2 id=&quot;how-agencies-combine-chrome-devtools-agents-with-scheduled-pagespeed-monitoring&quot; class=&quot;scroll-mt-24&quot;&gt;How agencies combine Chrome DevTools agents with scheduled PageSpeed monitoring&lt;/h2&gt;&lt;p&gt;A practical split that matches how delivery teams already work:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;During build. Use a Lighthouse AI agent on local and staging for accessibility, technical SEO, best practices, and optional agentic browsing when the product exposes agent tools. Paste Chrome’s example prompts and keep the failing audit list in the pull request.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;At release. Re-run the same priority templates on the staging hostname the client will accept, still with the agent or a manual Lighthouse pass if the agent tooling is unavailable.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;After release. Rely on scheduled PageSpeed Insights or Lighthouse runs across the portfolio, with budgets and alerts on the URLs that earn revenue or retention. That is the layer Apogee Watcher is built for: multi-tenant schedules, history, and client-ready reporting without asking a developer to babysit Chrome tabs.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Layer, do not replace. Coding agents do not remove the need for continuous monitoring any more than Lighthouse CI removes the need for field Core Web Vitals. They shorten the time from “UI changed” to “measurable defect named.” Monitoring shortens the time from “production changed” to “someone on the account knows.” If you want a fast baseline before you wire schedules, run a &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/free-domain-pagespeed-check-multi-page-reports&quot;&gt;free domain PageSpeed check&lt;/a&gt; to see multi-page lab results for a hostname. When you are ready to put priority URLs on a recurring cadence, follow &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/getting-started-apogee-watcher-step-by-step-setup-guide&quot;&gt;Getting Started with Apogee Watcher: A Step-by-Step Setup Guide&lt;/a&gt;.&lt;/p&gt;&lt;h2 id=&quot;common-mistakes-with-chrome-devtools-agent-lighthouse-audits&quot; class=&quot;scroll-mt-24&quot;&gt;Common mistakes with Chrome DevTools agent Lighthouse audits&lt;/h2&gt;&lt;h3&gt;Treating a green agent pass as production proof&lt;/h3&gt;&lt;p&gt;Local data, auth walls, and feature flags differ from what real users and the Chrome UX Report show. A clean mobile audit on staging can still leave desktop production amber on Interaction to Next Paint. Ship the fix, then confirm on the production URL with the same device form factor you care about in the retainer report.&lt;/p&gt;&lt;h3&gt;Auditing only the homepage&lt;/h3&gt;&lt;p&gt;Agents will audit whatever page is loaded. Homepages are convenient and often wrong for ecommerce and SaaS work. If checkout, pricing, or login is where money and trust live, load those routes before you ask for a Lighthouse AI agent run.&lt;/p&gt;&lt;h3&gt;Ignoring audit disruption on shared environments&lt;/h3&gt;&lt;p&gt;Resize and reload behaviour can interrupt demos and live editing. Chrome documents that Lighthouse may change viewport size while simulating devices. Schedule agent audits the same way you schedule Lighthouse CI: on purpose, not mid-call with a client watching the same tab.&lt;/p&gt;&lt;h3&gt;Confusing Lighthouse agentic browsing with SEO rankings&lt;/h3&gt;&lt;p&gt;Agentic browsing audits help you understand assistant interaction readiness. They are not a substitute for crawlability, content quality, or Core Web Vitals programmes you already sell. Keep the category in research notes until you and the client agree what a pass ratio means commercially.&lt;/p&gt;&lt;h3&gt;Skipping history after the coding agent finishes&lt;/h3&gt;&lt;p&gt;An agent conversation disappears when the chat ends. Agencies need trend lines and budget breaches stored against the site record. Without history, last week’s “we fixed contrast” claim is hard to prove in a monthly review, and the next developer repeats the same audit from scratch.&lt;/p&gt;&lt;h2 class=&quot;scroll-mt-24&quot;&gt;FAQ&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Does a Lighthouse AI agent replace PageSpeed Insights?&lt;/strong&gt;No. The agent uses Lighthouse categories in a developer workflow inside Chrome. PageSpeed Insights remains a common lab entry point for stakeholders, and scheduled PageSpeed Insights or Lighthouse API runs remain how you watch many URLs over time. Use the agent to fix; use monitoring to watch. For the wider comparison of spot checks versus automation, see our &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/pagespeed-insights-vs-automated-monitoring-when-manual-checks-arent-enough&quot;&gt;PageSpeed Insights versus automated monitoring&lt;/a&gt; guide.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Can coding agents audit pages that are not on the public internet?&lt;/strong&gt;Yes, within Chrome’s stated support: any page visible in the browser, including local servers and &lt;code&gt;file://&lt;/code&gt; HTML. That is one of the strongest reasons to use agents during build rather than waiting for a public staging URL. Confirm the same checks later on the hostname clients and crawlers actually hit.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Should we report agentic browsing scores to clients every month?&lt;/strong&gt;Only if you have agreed what the category means and how experimental it still is. Most retainers should keep leading with Core Web Vitals and clear lab Performance trends, then mention agentic browsing when a product roadmap or assistant integration makes it relevant. Point curious clients at the &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/lighthouse-agentic-browsing-scoring&quot;&gt;agentic browsing scoring explainer&lt;/a&gt; before you put pass ratios on a dashboard.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Where do budgets and alerts fit if developers already run agent audits?&lt;/strong&gt;Budgets and alerts cover the gap after merge: unexpected third-party tags, plugin updates, and content changes that never open a coding agent session. Agent audits reduce defects entering the branch. Monitoring reduces defects lingering in production unnoticed. Set budgets on the same priority URLs you used in the agent session so the definition of “good” does not drift between tools.&lt;/p&gt;&lt;hr&gt;&lt;p&gt;Chrome DevTools for agents makes Lighthouse a first-class tool in coding-agent workflows. Accessibility, SEO, best practices, and agentic browsing can be measured on the page under change, including local and staging hosts. Agencies win when they adopt that loop for delivery quality and keep scheduled, multi-site PageSpeed monitoring for everything that happens after the pull request merges. Start with Chrome’s documented prompts on your next UI branch, then put the same priority URLs on a schedule so the fix stays fixed.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/23585/automate-lighthouse-audits-with-ai-agents-what-chrome-devtools-means-for-agencies</guid>
<pubDate>Tue, 28 Jul 2026 00:32:22 +0000</pubDate>
</item>
<item>
<title>Lighthouse 100: Custom PHP vs WordPress vs Shopify</title>
<link>https://coderlegion.com/21114/lighthouse-100-custom-php-vs-wordpress-vs-shopify</link>
<description>
&lt;p&gt;&amp;lt;!-- ========== SCHEMAS ========== --&amp;gt;


&amp;lt;!-- Static schemas (WebSite, LocalBusiness, Organization, etc.) &amp;ndash; keep as in your original --&amp;gt;



?&amp;gt;








&amp;lt;!-- ========== ARTICLE CONTENT ========== --&amp;gt;
&lt;/p&gt;&lt;h1&gt;Lighthouse 100: Custom PHP vs WordPress vs Shopify&lt;/h1&gt;
&lt;div class=&quot;post-meta&quot;&gt;
    &lt;span class=&quot;post-date&quot;&gt;April 2026&lt;/span&gt;
    &lt;span class=&quot;post-read&quot;&gt;12 min read&lt;/span&gt;
&lt;/div&gt;

&lt;p class=&quot;intro&quot;&gt;&lt;/p&gt;&lt;p&gt;I&amp;rsquo;m Jacob Campbell, and a perfect Lighthouse score isn&amp;rsquo;t luck &amp;mdash; it&amp;rsquo;s the natural result of shipping only the code a page needs. A custom PHP site routinely loads in around 0.6 seconds and scores 100; the same content on a plugin-heavy WordPress or app-laden Shopify theme often lands at three to four seconds. Here&amp;rsquo;s how Lighthouse actually scores performance, why the platform gap is so wide, and what it takes to reach 100.&lt;/p&gt;

&lt;h2&gt;&lt;/h2&gt;
&lt;p&gt;&lt;/p&gt;
&lt;ul&gt;
    &lt;/ul&gt;
&lt;p&gt;Your platform choice is the largest variable. Let&amp;rsquo;s prove it with hard numbers.&lt;/p&gt;

&lt;h2&gt;&lt;/h2&gt;
&lt;p&gt;&lt;/p&gt;
&lt;ul&gt;
    &lt;/ul&gt;
&lt;p&gt;&lt;/p&gt;

&lt;div class=&quot;comparison-table&quot;&gt;
    &lt;table style=&quot;width:100%; border-collapse: collapse; background: #0f1528; border-radius: 12px; overflow: hidden;&quot;&gt;
        &lt;thead style=&quot;background: #1a2542;&quot;&gt;
            &lt;tr&gt;
                            &lt;/tr&gt;
        &lt;/thead&gt;
        &lt;tbody&gt;
                    &lt;/tbody&gt;
    &lt;/table&gt;
&lt;/div&gt;

&lt;h2&gt;Breaking Down the Numbers &amp;ndash; Why Such a Gap?&lt;/h2&gt;

&lt;h3&gt;&lt;/h3&gt;
&lt;p&gt;&lt;/p&gt;

&lt;h3&gt;&lt;/h3&gt;
&lt;p&gt;&lt;/p&gt;

&lt;h3&gt;&lt;/h3&gt;
&lt;p&gt;&lt;/p&gt;

&lt;h3&gt;&lt;/h3&gt;
&lt;p&gt;&lt;/p&gt;

&lt;h2&gt;&lt;/h2&gt;
&lt;p&gt;&lt;/p&gt;
&lt;ul&gt;
    &lt;/ul&gt;
&lt;p&gt;&lt;/p&gt;

&lt;h2&gt;&lt;/h2&gt;

&lt;h3&gt;&lt;/h3&gt;
&lt;p&gt;&lt;/p&gt;

&lt;h3&gt;&lt;/h3&gt;
&lt;p&gt;&lt;/p&gt;
&lt;ul&gt;
    &lt;/ul&gt;
&lt;p&gt;&lt;/p&gt;

&lt;h3&gt;&lt;/h3&gt;
&lt;p&gt;&lt;/p&gt;
&lt;ul&gt;
    &lt;/ul&gt;
&lt;p&gt;&lt;/p&gt;

&lt;h2&gt;&lt;/h2&gt;
&lt;p&gt;&lt;/p&gt;
&lt;table style=&quot;width:100%; border-collapse: collapse; background:#0f1528; border-radius:12px; overflow:hidden;&quot;&gt;
    &lt;thead style=&quot;background:#1a2542;&quot;&gt;
        &lt;tr&gt;
                    &lt;/tr&gt;
    &lt;/thead&gt;
    &lt;tbody&gt;
            &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;/p&gt;

&lt;h2&gt;&lt;/h2&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;

&lt;div class=&quot;article-cta&quot;&gt;
    &lt;a href=&quot;/contact&quot;&gt;&lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;&lt;small&gt;&lt;em&gt;&lt;/em&gt;&lt;/small&gt;&lt;/p&gt;
</description>
<category>Other</category>
<guid isPermaLink="true">https://coderlegion.com/21114/lighthouse-100-custom-php-vs-wordpress-vs-shopify</guid>
<pubDate>Mon, 13 Jul 2026 07:45:45 +0000</pubDate>
</item>
<item>
<title>When Lighthouse CI maintenance in CI/CD pipelines becomes a second job</title>
<link>https://coderlegion.com/21891/when-lighthouse-ci-maintenance-in-ci-cd-pipelines-becomes-a-second-job</link>
<description>&lt;p&gt;Performance budget gates in GitHub Actions are free until someone owns twelve client workflows, Chrome drift, and client reporting. How agencies split Lighthouse CI from managed PageSpeed monitoring.&lt;/p&gt;
&lt;p&gt;The Slack thread started with a screenshot of a green GitHub Actions run. By the third reply someone had pasted a Lighthouse JSON artefact, a link to a Chrome release note, and a question nobody wanted to own: &quot;Which client repository still pins Lighthouse 10?&quot;&lt;/p&gt;
&lt;p&gt;That is the week Lighthouse CI stopped being a merge gate and became a second job. The pipeline still passed and the portfolio still needed evidence, but the difference was who paid in hours: the developer shipping a feature, or the one person who inherited every &lt;code&gt;lighthouserc&lt;/code&gt; file across client repositories.&lt;/p&gt;
&lt;h3 id=&quot;when-does-lighthouse-ci-maintenance-outgrow-a-ci-cd-pipeline-&quot;&gt;When does Lighthouse CI maintenance outgrow a CI/CD pipeline?&lt;/h3&gt;
&lt;p&gt;Lighthouse CI earns its place early. You wire assertions on a preview URL, block a CLS regression, and the team trusts the red build. The cost is front-loaded configuration, not ongoing calendar time.&lt;/p&gt;
&lt;p&gt;The shift happens when success creates obligations a CI/CD pipeline was never designed to carry:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Every new client repository needs a copied workflow, pinned Chrome, and preview URL rules that match their host.&lt;/li&gt;
&lt;li&gt;Assertions need tuning after flaky LCP on cold runners, so thresholds loosen until they barely catch real regressions.&lt;/li&gt;
&lt;li&gt;Account managers ask for client-ready reports, and the only export is a CI/CD artefact someone must turn into slides.&lt;/li&gt;
&lt;li&gt;Production URLs outside the two preview paths regress while the job stays green.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;At that point you are not &quot;running Lighthouse CI in a pipeline.&quot; You are operating a small internal product: version pins, runner hygiene, assertion policy, and reporting glue. For a single product team that can be fine. For an agency portfolio it competes with billable delivery.&lt;/p&gt;
&lt;h3 id=&quot;how-do-you-know-lighthouse-ci-in-ci-cd-became-an-unpaid-side-role-&quot;&gt;How do you know Lighthouse CI in CI/CD became an unpaid side role?&lt;/h3&gt;
&lt;p&gt;We treat these as signals to shrink CI/CD scope or add a managed monitoring layer, not as moral failure. Teams hit them around five to fifteen client sites, sometimes sooner when preview hosts differ wildly.&lt;/p&gt;
&lt;h4 id=&quot;flaky-lighthouse-ci-runs-on-github-actions&quot;&gt;Flaky Lighthouse CI runs on GitHub Actions&lt;/h4&gt;
&lt;p&gt;Engineers merge after the third &quot;Re-run failed jobs&quot; click because INP moved six points on a shared runner. When the gate is noise, people route around it.&lt;/p&gt;
&lt;h4 id=&quot;-lhci-cli-and-lighthouse-version-drift-across-repositories&quot;&gt;@lhci/cli and Lighthouse version drift across repositories&lt;/h4&gt;
&lt;p&gt;One repository uses &lt;code&gt;@lhci/cli&lt;/code&gt; 0.13, another 0.14, Lighthouse 11 on one client and 10 on another. Nobody can say which assertion set is authoritative without opening six pull requests.&lt;/p&gt;
&lt;h4 id=&quot;preview-url-versus-production-green-ci-cd-red-pagespeed-insights&quot;&gt;Preview URL versus production: green CI/CD, red PageSpeed Insights&lt;/h4&gt;
&lt;p&gt;The CI/CD job guards &lt;code&gt;/&lt;/code&gt; on a Netlify preview while production serves &lt;code&gt;/checkout&lt;/code&gt; from a different CDN rule. Sponsors see red on PageSpeed Insights; developers point at a green pipeline run and both sides are partially right.&lt;/p&gt;
&lt;h4 id=&quot;lighthouse-ci-artefacts-instead-of-client-ready-performance-reports&quot;&gt;Lighthouse CI artefacts instead of client-ready performance reports&lt;/h4&gt;
&lt;p&gt;Monthly retainers need a short narrative: which URLs broke budget, when, and what changed. If the answer lives in downloaded JSON and a manual chart, someone is doing monitoring work outside the pipeline, unpaid.&lt;/p&gt;
&lt;h4 id=&quot;one-engineer-as-the-default-lighthouse-ci-maintainer&quot;&gt;One engineer as the default Lighthouse CI maintainer&lt;/h4&gt;
&lt;p&gt;One senior developer becomes &quot;the Lighthouse person,&quot; fixes workflows between client calls, and resents every Chrome update. That is a job description, not a YAML tweak.&lt;/p&gt;
&lt;p&gt;If three or more patterns sound familiar, Lighthouse CI is already a second job. The fix is not deleting the pipeline check. It is deciding which hours belong in merge protection and which belong in scheduled monitoring with client-ready output.&lt;/p&gt;
&lt;h3 id=&quot;which-performance-budget-checks-should-lighthouse-ci-enforce-in-ci-cd-&quot;&gt;Which performance budget checks should Lighthouse CI enforce in CI/CD?&lt;/h3&gt;
&lt;p&gt;We keep the CI/CD slice thin on purpose. Merge protection should answer a narrow question: did this candidate build break budgets on the one or two preview URLs we trust for this repository?&lt;/p&gt;
&lt;p&gt;Keep as errors when the check is stable and the developer on the pull request can fix the cause:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CLS on in-scope templates where layout is the likely regression.&lt;/li&gt;
&lt;li&gt;Bundle or script byte ceilings when the build exposes an artefact.&lt;/li&gt;
&lt;li&gt;Total blocking time or main-thread proxies when the change touches JavaScript entry points.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Warn, do not block, when preview parity is weak: cold CDN LCP, ads on staging, INP without enough repetitions to trust a median.&lt;/p&gt;
&lt;p&gt;Do not ask CI/CD to replace production monitoring: field CrUX exports, full sitemap crawls, rank proxies, or every revenue template on every docs-only commit. Those checks belong on a schedule against production URLs, with alerts that account managers can forward.&lt;/p&gt;
&lt;p&gt;The wiring patterns, assertion keys, and GitHub Actions sketch live in our step-by-step guide: &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/how-to-set-up-performance-budgets-in-ci-cd-pipelines?utm_source=hashnode&amp;amp;utm_medium=referral&amp;amp;utm_campaign=hashnode-lighthouse-ci-cicd-second-job&quot;&gt;How to set up performance budgets in CI/CD pipelines&lt;/a&gt;. Use that guide to implement a small gate; use the criteria above to decide how small.&lt;/p&gt;
&lt;h3 id=&quot;lighthouse-ci-versus-managed-monitoring-why-agencies-hit-build-versus-buy-pressure-early&quot;&gt;Lighthouse CI versus managed monitoring: why agencies hit build-versus-buy pressure early&lt;/h3&gt;
&lt;p&gt;Lighthouse CI is open source and runner-native, which makes it the default first step. Managed PageSpeed monitoring adds invoice line items, which makes teams delay the decision until the hidden invoice arrives: senior hours spent keeping workflows honest.&lt;/p&gt;
&lt;p&gt;The build path scales poorly across repositories because CI/CD is repository-centric and agencies are portfolio-centric. Copying configuration per client multiplies drift. Preview URL changes when a client moves hosts. Authentication on staging breaks collection until someone scripts login. Each exception lands on the same maintainer.&lt;/p&gt;
&lt;p&gt;The buy path trades some control for repetition: scheduled lab runs across many URLs, history, thresholds shared with client reports, and alerts when production templates cross budget. It does not replace merge gates on preview; it absorbs the work a pipeline should never have carried: full URL lists, post-deploy cadence, and evidence sponsors can read without terminal access.&lt;/p&gt;
&lt;p&gt;We wrote the comparison for agency leads evaluating that trade explicitly: &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/lighthouse-ci-vs-managed-monitoring-build-vs-buy-agencies?utm_source=hashnode&amp;amp;utm_medium=referral&amp;amp;utm_campaign=hashnode-lighthouse-ci-cicd-second-job&quot;&gt;Lighthouse CI versus managed monitoring: build versus buy for agencies&lt;/a&gt;. The headline question is not &quot;free versus paid.&quot; It is whether your team wants to operate monitoring infrastructure or operate client sites.&lt;/p&gt;
&lt;h3 id=&quot;how-to-shrink-lighthouse-ci-scope-in-ci-cd-pipelines-without-losing-merge-protection&quot;&gt;How to shrink Lighthouse CI scope in CI/CD pipelines without losing merge protection&lt;/h3&gt;
&lt;p&gt;When CI/CD became a second job for us, the recovery plan had four moves. None required removing Lighthouse from the pipeline entirely.&lt;/p&gt;
&lt;h4 id=&quot;limit-lighthouse-ci-to-two-preview-urls-per-client-repository&quot;&gt;Limit Lighthouse CI to two preview URLs per client repository&lt;/h4&gt;
&lt;p&gt;Two preview paths maximum on small retainers: homepage plus one revenue or app-shell template agreed in the statement of work. Everything else lives in scheduled monitoring.&lt;/p&gt;
&lt;h4 id=&quot;one-performance-budget-document-for-ci-cd-gates-and-client-reports&quot;&gt;One performance budget document for CI/CD gates and client reports&lt;/h4&gt;
&lt;p&gt;Copy numbers from the same budget document monitoring uses. If CI/CD gates and the client report disagree on thresholds, engineers ignore both.&lt;/p&gt;
&lt;h4 id=&quot;demote-flaky-lcp-to-warnings-keep-cls-and-bundle-size-as-errors&quot;&gt;Demote flaky LCP to warnings; keep CLS and bundle size as errors&lt;/h4&gt;
&lt;p&gt;Demote flaky LCP to warnings until preview matches production behaviour on paper. Keep CLS and bundle ceilings as errors people act on.&lt;/p&gt;
&lt;h4 id=&quot;document-pre-merge-ci-cd-versus-post-deploy-monitoring-in-the-readme&quot;&gt;Document pre-merge CI/CD versus post-deploy monitoring in the README&lt;/h4&gt;
&lt;p&gt;CI/CD answers pre-merge; monitoring answers post-deploy. Write that split in the repository README so account teams stop asking the pipeline to prove checkout on Friday's release.&lt;/p&gt;
&lt;p&gt;Layer managed monitoring beside the CI/CD job rather than inflating YAML until every pull request waits ten minutes on Chrome. Multi-tenant monitors exist precisely because portfolio evidence does not belong inside each client's GitHub Actions bill.&lt;/p&gt;
&lt;h3 id=&quot;lighthouse-ci-in-ci-cd-versus-scheduled-pagespeed-monitoring-agency-split-for-one-repository&quot;&gt;Lighthouse CI in CI/CD versus scheduled PageSpeed monitoring: agency split for one repository&lt;/h3&gt;
&lt;p&gt;For a typical agency client on a modern JavaScript stack, we aim for under ten minutes of CI/CD web performance time and zero manual JSON exports per month.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Phase &lt;/th&gt;&lt;th&gt;Tooling &lt;/th&gt;&lt;th&gt;Question&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Pre-merge &lt;/td&gt;&lt;td&gt;Lighthouse CI plus one bundle guard &lt;/td&gt;&lt;td&gt;Did this branch regress CLS or script weight on the two preview URLs in scope?&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Post-deploy &lt;/td&gt;&lt;td&gt;Scheduled PageSpeed monitoring &lt;/td&gt;&lt;td&gt;Are production templates still inside budget on the cadence we promised?&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Reporting &lt;/td&gt;&lt;td&gt;Monitoring product export &lt;/td&gt;&lt;td&gt;What do we send the sponsor without opening a terminal?&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Green in CI/CD and red in the Friday report means the split failed, not that someone lied. Either preview parity is wrong, the URL list in monitoring is right and the pipeline was too narrow, or the regression shipped through a path CI/CD never watched. All three are operational fixes, not reasons to add a fourth Lighthouse run on every push.&lt;/p&gt;
&lt;h3 id=&quot;audit-lighthouse-ci-maintenance-before-you-copy-the-workflow-to-another-client&quot;&gt;Audit Lighthouse CI maintenance before you copy the workflow to another client&lt;/h3&gt;
&lt;p&gt;Pick the client repository where the CI/CD job failed most often last quarter. Answer honestly:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Who last updated &lt;code&gt;lighthouserc&lt;/code&gt; and the Chrome pin?&lt;/li&gt;
&lt;li&gt;How many hours went to flaky re-runs versus feature work?&lt;/li&gt;
&lt;li&gt;Which production URL regressed while the pipeline stayed green?&lt;/li&gt;
&lt;li&gt;What did the sponsor receive that was not a raw artefact?&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If the maintainer has a name and the sponsor answer is &quot;a screenshot from PageSpeed Insights,&quot; you already have a second job. Implement the thin CI/CD template from &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/how-to-set-up-performance-budgets-in-ci-cd-pipelines?utm_source=hashnode&amp;amp;utm_medium=referral&amp;amp;utm_campaign=hashnode-lighthouse-ci-cicd-second-job&quot;&gt;performance budgets in CI/CD pipelines&lt;/a&gt;, then read &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.com/blog/lighthouse-ci-vs-managed-monitoring-build-vs-buy-agencies?utm_source=hashnode&amp;amp;utm_medium=referral&amp;amp;utm_campaign=hashnode-lighthouse-ci-cicd-second-job&quot;&gt;Lighthouse CI versus managed monitoring&lt;/a&gt; before copying the workflow into client seven.&lt;/p&gt;
&lt;p&gt;Merge gates should block merges you would roll back. Everything else belongs on a schedule, with owners, on the full URL list the retainer names.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Originally published on &lt;a rel=&quot;nofollow&quot; href=&quot;https://apogeewatcher.hashnode.dev/lighthouse-ci-maintenance-cicd-pipelines-second-job&quot;&gt;Hashnode&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/21891/when-lighthouse-ci-maintenance-in-ci-cd-pipelines-becomes-a-second-job</guid>
<pubDate>Sat, 04 Jul 2026 08:27:36 +0000</pubDate>
</item>
</channel>
</rss>