<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Apogee Watcher</title>
    <description>The latest articles on DEV Community by Apogee Watcher (@apogeewatcher).</description>
    <link>https://dev.to/apogeewatcher</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3769723%2Fa33f1555-0cd4-4f44-b524-a9608ed39a2c.png</url>
      <title>DEV Community: Apogee Watcher</title>
      <link>https://dev.to/apogeewatcher</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/apogeewatcher"/>
    <language>en</language>
    <item>
      <title>Put Chrome Stable on the same calendar as your deploys</title>
      <dc:creator>Apogee Watcher</dc:creator>
      <pubDate>Wed, 23 Sep 2026 06:28:11 +0000</pubDate>
      <link>https://dev.to/apogeewatcher/put-chrome-stable-on-the-same-calendar-as-your-deploys-4cp5</link>
      <guid>https://dev.to/apogeewatcher/put-chrome-stable-on-the-same-calendar-as-your-deploys-4cp5</guid>
      <description>&lt;p&gt;Field Largest Contentful Paint can move while your application release calendar stays empty. The spreadsheet already lists app deploys, CDN config changes, tag-manager publishes, and RUM or instrumentation bumps. From Chrome 153 Stable on 8 September 2026, Chrome ships a new Stable (and Beta) every two weeks on Desktop, Android, and iOS. Leave Chrome Stable off that same sheet and you will keep blaming ghost commits for shifts that are only population mix.&lt;/p&gt;

&lt;p&gt;The ritual fix is dull on purpose: browser Stable and Beta sit next to the changes you already annotate, one named owner writes the date before the graph moves, and the monthly pack stops inventing regressions. CrUX math and sample thresholds live on our Watcher how-to. Ownership of the calendar is the piece that makes those reports honest.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Chrome Stable belongs beside deploys
&lt;/h2&gt;

&lt;p&gt;Chrome User Experience Report field data is a rolling blend of real Chrome sessions, not a snapshot of yesterday’s build. When a new Stable major enters that mix, paint timing, decoding, lazy-load heuristics, or interaction scheduling can shift for the same URL while your HTML and bundles stay byte-identical. Faster Stable cadence simply raises how often that mix changes inside one reporting window.&lt;/p&gt;

&lt;p&gt;Google’s &lt;a href="https://developer.chrome.com/blog/chrome-two-week-release" rel="noopener noreferrer"&gt;two-week release announcement&lt;/a&gt; is the schedule source. From Chrome 153, Beta and Stable promote every two weeks; Extended Stable keeps its eight-week enterprise cycle. Firefox has been running a similar fortnightly experiment around the same period. Agencies that only annotated application cuts in 2025 now need browser rows in 2026, or every Stable Tuesday becomes an unexplained ticket.&lt;/p&gt;

&lt;p&gt;Harry Roberts put the measurement framing cleanly in &lt;a href="https://csswizardry.com/2026/08/web-perf-wednesday-006-faster-browser-releases-change-your-rum-population/" rel="noopener noreferrer"&gt;Web-Perf Wednesday 006&lt;/a&gt;: faster browser releases change the RUM population you are averaging. The agency failure mode is narrower than the measurement essay. Teams open a regression hunt because the shared calendar never recorded that Chrome moved.&lt;/p&gt;

&lt;h2&gt;
  
  
  What belongs on one shared release calendar
&lt;/h2&gt;

&lt;p&gt;One calendar per client portfolio beats five tools that never meet. Useful rows are the changes that can move field percentiles, or look like they did. Share those rows on one sheet and a quiet week has a readable explanation instead of five disconnected notification emails.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Change type&lt;/th&gt;
&lt;th&gt;What to record&lt;/th&gt;
&lt;th&gt;Why it belongs&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Application deploy&lt;/td&gt;
&lt;td&gt;Environment, git SHA or release tag, money URLs touched&lt;/td&gt;
&lt;td&gt;Origin change you control&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CDN / cache / edge&lt;/td&gt;
&lt;td&gt;Config version, purge scope, rule ID&lt;/td&gt;
&lt;td&gt;Delivery change without an app tag&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tag manager / third-party&lt;/td&gt;
&lt;td&gt;Container version, publish time&lt;/td&gt;
&lt;td&gt;Main-thread and LCP side effects&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RUM / instrumentation&lt;/td&gt;
&lt;td&gt;Library version, sampling or route rules&lt;/td&gt;
&lt;td&gt;Collection change that looks like a metric shift&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Chrome Stable / Beta&lt;/td&gt;
&lt;td&gt;Milestone, channel, scheduled date&lt;/td&gt;
&lt;td&gt;Browser population entering field windows&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Firefox Stable / Beta&lt;/td&gt;
&lt;td&gt;Milestone, channel, scheduled date&lt;/td&gt;
&lt;td&gt;Same population logic for Firefox-heavy audiences&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Extended Stable (if relevant)&lt;/td&gt;
&lt;td&gt;Cohort lag vs consumer Stable&lt;/td&gt;
&lt;td&gt;Enterprise mix that updates on a different clock&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The browser date is an &lt;strong&gt;annotation&lt;/strong&gt;, not a claim that every visitor updated at once. First-party RUM helps here: version share beside that marker shows how fast the cohort actually moved. Dates belong on the sheet the same week you plan app cuts (from &lt;a href="https://chromestatus.com/roadmap" rel="noopener noreferrer"&gt;Chrome Status&lt;/a&gt;, Chromium dashboards, and the Firefox release calendar), not after a client asks why LCP went amber.&lt;/p&gt;

&lt;p&gt;Beta still earns a row. Chrome ships a Beta about three weeks before Stable, so there is time to check real journeys, metric completion, soft-navigation detection, and browser-specific dimensions. That is a routine rehearsal, not a late smoke test the day before Stable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Name an owner before the graph moves
&lt;/h2&gt;

&lt;p&gt;Annotations without an owner die in the same week they are invented. The workable pattern is one named person (or rotating role) who adds Chrome and Firefox Stable and Beta dates &lt;strong&gt;before&lt;/strong&gt; field charts update. In most retainers that is the technical lead who already owns the monthly Core Web Vitals pack, not “whoever notices Slack first.”&lt;/p&gt;

&lt;p&gt;A workable weekly habit looks like this. On Monday, skim the next two Stable dates and paste them onto the shared calendar. After any app, CDN, tag, or RUM change, add that row the same day. When field LCP, INP, or CLS moves, the calendar opens &lt;strong&gt;before&lt;/strong&gt; the bug tracker: if a browser milestone sits inside the collection window and the origin rows are quiet, population mix is the first question, not a phantom deploy.&lt;/p&gt;

&lt;p&gt;Waiting until the percentile has already moved is too late. With a major every fortnight, “we will annotate when something looks weird” means the annotation arrives after the client argument has started. The calendar is useful when the date was already written the moment someone first noticed the amber band.&lt;/p&gt;

&lt;h2&gt;
  
  
  When field LCP shifts with no deploy: check population mix first
&lt;/h2&gt;

&lt;p&gt;Run a short triage before you escalate:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Confirm the app, CDN, tag-manager, and instrumentation rows for the collection window are empty (or explain the ones that are not).&lt;/li&gt;
&lt;li&gt;Check whether a Chrome or Firefox Stable (or Extended Stable lag) sits inside the same dates.&lt;/li&gt;
&lt;li&gt;Look at version share and sample size before trusting a single-major p75 slice.&lt;/li&gt;
&lt;li&gt;Keep an &lt;strong&gt;unsegmented&lt;/strong&gt; field series as the executive headline; use browser-major slices as engineer appendix material.&lt;/li&gt;
&lt;li&gt;Pair with a scheduled lab run on the same money URLs so you can say the origin critical path did not move this week.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Population mix means the aggregate changed because the audience composition changed: more sessions on a new Stable, fewer on the previous major, or a campaign that shifted which templates dominate. Site regression is narrower. The same browser version and a similar journey got worse after a change you control. Confusing the two burns engineering time and weakens the next real alert.&lt;/p&gt;

&lt;p&gt;For the full field-window and sample-threshold treatment, &lt;a href="https://apogeewatcher.com/blog/when-lcp-moves-nobody-deployed-browser-release-cadence-28-day-field-window?utm_source=hashnode&amp;amp;utm_medium=referral&amp;amp;utm_campaign=put-chrome-stable-on-the-same-calendar-as-your-deploys" rel="noopener noreferrer"&gt;When LCP Moves and Nobody Deployed: Browser Release Cadence and Your 28-Day Field Window&lt;/a&gt; owns the CrUX clocks and reporting templates. The job here is smaller. Put Chrome on the sheet before anyone argues about a ghost commit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Browser release cadence versus CrUX pipeline lag
&lt;/h2&gt;

&lt;p&gt;Two different delays get conflated in client calls. &lt;strong&gt;Pipeline lag&lt;/strong&gt; is when a verified fix (or a real regression) takes time to appear in published CrUX / PageSpeed Insights field sections because collection and processing are not instant. &lt;strong&gt;Browser cadence inside the window&lt;/strong&gt; is different: the rolling 28-day mix already includes more than one Stable major, so the percentile can move with no origin change at all.&lt;/p&gt;

&lt;p&gt;“We shipped Friday and field still looks old” points at &lt;a href="https://apogeewatcher.com/blog/crux-pipeline-delays-late-field-data-client-reports?utm_source=hashnode&amp;amp;utm_medium=referral&amp;amp;utm_campaign=put-chrome-stable-on-the-same-calendar-as-your-deploys" rel="noopener noreferrer"&gt;CrUX pipeline delays and late field data in client reports&lt;/a&gt;. “Nobody deployed and LCP still moved” points at the shared calendar and population mix. Lab green beside field amber is a third conversation, so folding all three into one vague “CrUX is slow” answer helps nobody.&lt;/p&gt;

&lt;p&gt;Scheduled monitoring still helps. Same-week lab evidence on money URLs, portfolio alerts on your thresholds, and dated annotations clients can read without a statistics lecture make the calendar useful in the monthly pack. Watcher layers onto that workflow. It does not replace the release calendar you already maintain.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Does every Chrome Stable need a client email?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
No. Most Stable dates are quiet annotations on the internal sheet. Client email makes sense when field bands move &lt;em&gt;and&lt;/em&gt; the calendar shows a browser milestone with no origin change, or when sample counts are large enough that a major-specific shift is worth explaining in the monthly pack.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What if we only have CrUX, not first-party RUM?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Stable and Beta still belong on the calendar. Without version share charts you cannot prove mix as tightly, so the honest pack leans on unsegmented field series, lab pairing, and careful wording (“browser release inside the collection window” rather than “Chrome 153 caused this”).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Should we slice every report by Chrome major?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Only when sample counts support it. Thin major slices manufacture weekly false regressions that look decisive in a slide and evaporate under scrutiny. Unsegmented headlines stay safer for leadership; major splits belong in engineering follow-up.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where do Extended Stable clients fit?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
On their own calendar row. They can lag consumer Stable for weeks, so a retail audience and a locked-down corporate audience on the same template can read different field bands with no deploy on either side. That lag is expected; it is not an unexplained regression until the calendar says otherwise.&lt;/p&gt;

&lt;h2&gt;
  
  
  Put the browser on the sheet this week
&lt;/h2&gt;

&lt;p&gt;The release calendar you already use for deploys is enough. Chrome Stable and Beta for the next month go on it now, Firefox too if that traffic matters, and the owner’s name sits at the top of the tab. Next time field LCP moves on a quiet week, you have a dated answer instead of a fictional commit. After the ritual sticks, the Watcher guides linked above carry the deeper reporting playbook; when the same annotations need to span a multi-client portfolio, &lt;a href="https://apogeewatcher.com/sign-up?utm_source=hashnode&amp;amp;utm_medium=referral&amp;amp;utm_campaign=put-chrome-stable-on-the-same-calendar-as-your-deploys" rel="noopener noreferrer"&gt;start a Watcher trial&lt;/a&gt;.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://developer.chrome.com/blog/chrome-two-week-release" rel="noopener noreferrer"&gt;Get features faster with Chrome's two-week release cycle&lt;/a&gt; (Chrome for Developers)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://csswizardry.com/2026/08/web-perf-wednesday-006-faster-browser-releases-change-your-rum-population/" rel="noopener noreferrer"&gt;Web-Perf Wednesday 006 – Faster Browser Releases Change Your RUM Population&lt;/a&gt; (CSS Wizardry)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://apogeewatcher.com/blog/when-lcp-moves-nobody-deployed-browser-release-cadence-28-day-field-window" rel="noopener noreferrer"&gt;When LCP Moves and Nobody Deployed: Browser Release Cadence and Your 28-Day Field Window&lt;/a&gt; (Apogee Watcher)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://apogeewatcher.com/blog/crux-pipeline-delays-late-field-data-client-reports" rel="noopener noreferrer"&gt;CrUX pipeline delays and late field data in client reports&lt;/a&gt; (Apogee Watcher)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://chromestatus.com/roadmap" rel="noopener noreferrer"&gt;Chrome Status roadmap&lt;/a&gt; (Chrome)&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webperf</category>
      <category>corewebvitals</category>
      <category>agency</category>
      <category>chrome</category>
    </item>
    <item>
      <title>Oh Dear vs Apogee Watcher: Uptime Suite vs Core Web Vitals Portfolio Monitoring</title>
      <dc:creator>Apogee Watcher</dc:creator>
      <pubDate>Wed, 23 Sep 2026 06:25:02 +0000</pubDate>
      <link>https://dev.to/apogeewatcher/oh-dear-vs-apogee-watcher-uptime-suite-vs-core-web-vitals-portfolio-monitoring-736</link>
      <guid>https://dev.to/apogeewatcher/oh-dear-vs-apogee-watcher-uptime-suite-vs-core-web-vitals-portfolio-monitoring-736</guid>
      <description>&lt;p&gt;&lt;a href="https://ohdear.app/" rel="noopener noreferrer"&gt;Oh Dear&lt;/a&gt; is the tool many agencies use when they want one place for “is the site up?” plus SSL, DNS, broken links, status pages, and a daily Lighthouse score. That package is strong when the primary risk is downtime, certificate expiry, or a status page clients can trust.&lt;/p&gt;

&lt;p&gt;Apogee Watcher answers a different question: how do you keep scheduled PageSpeed Insights coverage honest across many client origins when the failure mode is “still returns 200, but LCP and INP are amber,” and when you need multi-tenant roles, discovery, and CrUX context without turning monitoring into a second DevOps product? We store Google’s PageSpeed Insights API results (Lighthouse lab plus CrUX where Google publishes field data) inside organisations with Admin, Manager, and Viewer roles. We do not sell uptime ping suites, public status pages, or SSL certificate monitoring as a product line.&lt;/p&gt;

&lt;p&gt;The comparison below is about workflow fit for agencies, not about declaring a universal winner. Feature lists and plan limits change on both sides, so confirm each vendor’s site before you buy and treat any table as a snapshot rather than a contract. Searching for an Oh Dear alternative often mixes two jobs: replace an uptime suite, or keep Oh Dear and add a Core Web Vitals layer. Those are different purchase decisions.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Oh Dear is genuinely good at
&lt;/h2&gt;

&lt;p&gt;Oh Dear’s public positioning is an all-in-one website health monitor. Marketing copy lists uptime, SSL certificate health, broken links and mixed content, DNS and domain expiry, cron / scheduled-task heartbeats, ping and TCP checks, public status pages, and performance / Lighthouse checks under one login. Every plan includes the full feature set; you pay for site capacity, not for unlocking SSO, unlimited users, or notification destinations (&lt;a href="https://ohdear.app/pricing" rel="noopener noreferrer"&gt;pricing&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;For agencies that already lose evenings to “the site is down” tickets, that bundle is compelling. Second-location verification of alerts, branded status pages on your domain, monthly client reports, and reseller-style access are designed so clients see your brand while Oh Dear measures reachability. Teams that want fewer point tools for uptime-adjacent work (and one place to route Slack or PagerDuty) often shortlist Oh Dear for that reason alone.&lt;/p&gt;

&lt;p&gt;None of that is theatre. If your brief is “know when client origins fail, certificates expire, or status pages need an update,” Oh Dear is a serious primary candidate. UptimeRobot-class free checkers, StatusCake, and similar products compete on the uptime axis; we are not claiming Watcher replaces that axis.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Oh Dear performance and Lighthouse checks actually measure
&lt;/h2&gt;

&lt;p&gt;Oh Dear uses the word &lt;strong&gt;performance&lt;/strong&gt; for more than one check, and agencies need the split before they compare it to a PageSpeed programme.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;HTTP performance monitoring&lt;/strong&gt; (documented on &lt;a href="https://ohdear.app/features/performance-monitoring" rel="noopener noreferrer"&gt;Oh Dear performance monitoring&lt;/a&gt;) times the same request Oh Dear already makes for uptime. It stores DNS, TCP, TLS, server processing (time to first byte), and content download, then alerts on a millisecond budget or a sudden change against a recent baseline. Samples arrive with the uptime fetch (about once a minute); slowdowns are evaluated on a fifteen-minute cadence. Oh Dear is explicit that this is &lt;strong&gt;synthetic&lt;/strong&gt;, not real-user monitoring, and that it is not a scripted checkout journey.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lighthouse SEO monitoring&lt;/strong&gt; (documented on &lt;a href="https://ohdear.app/features/lighthouse-seo-monitoring" rel="noopener noreferrer"&gt;Oh Dear Lighthouse SEO monitoring&lt;/a&gt;) runs Google Lighthouse on a schedule (daily in the product story). It tracks performance, accessibility, best-practices, and SEO category scores, then alerts when scores fall below thresholds. That is a real browser lab audit. It is closer to what teams mean by “pagespeed,” and it catches deploys that tank a Lighthouse score overnight.&lt;/p&gt;

&lt;p&gt;Those checks sit beside uptime. They do not automatically create a multi-URL Core Web Vitals portfolio with money-page inventories, CrUX field bands beside lab runs, or agency-wide discovery when a client adds twenty new templates. Response-time budgets answer “is the origin late?” Lighthouse answers “did this URL’s lab scores move?” PageSpeed Insights field sections answer “what did Chrome users experience over the collection window?” Mixing those three into one “performance is covered” sentence is how retainers buy the wrong primary tool.&lt;/p&gt;

&lt;p&gt;For the wider lab-versus-field map, read &lt;a href="https://apogeewatcher.com/blog/when-to-use-synthetic-vs-real-user-monitoring-performance" rel="noopener noreferrer"&gt;When to Use Synthetic vs Real User Monitoring for Performance&lt;/a&gt;. For how agencies assemble layers after a tools shortlist, use &lt;a href="https://apogeewatcher.com/blog/agency-pagespeed-stacks-2026" rel="noopener noreferrer"&gt;3 Agency PageSpeed Stacks for 2026&lt;/a&gt;. Together they keep measurement jobs separate from vendor brands.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where agencies feel friction when CWV is the real job
&lt;/h2&gt;

&lt;p&gt;Oh Dear friction for PageSpeed-led retainers usually shows up in three places, even when the product is excellent at its core job.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pricing shaped by site count, not by CWV depth.&lt;/strong&gt; Public &lt;a href="https://ohdear.app/pricing" rel="noopener noreferrer"&gt;Oh Dear pricing&lt;/a&gt; scales with sites and servers: 25 sites at Studio &lt;strong&gt;$109/month&lt;/strong&gt;, 50 at Agency &lt;strong&gt;$165/month&lt;/strong&gt;, 100 at Portfolio &lt;strong&gt;$275/month&lt;/strong&gt;. That is predictable when every site needs the full uptime bundle. It is a different equation when you mainly need scheduled mobile and desktop PageSpeed on priority URLs across many hosts, and you already own Pingdom or another uptime tool. Matching “everything included” elsewhere can still mean paying uptime economics for a CWV-only brief.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Performance language that sounds like a CWV suite.&lt;/strong&gt; HTTP response-time alerts and daily Lighthouse scores are valuable. They are not the same as continuous PageSpeed Insights history with CrUX-in-result context, attention-free triage across a domain, or budgets tied to LCP / INP / CLS thresholds your SEO retainer already uses in client decks. Buyers who search “oh dear vs pagespeed” are often trying to name that gap without a taxonomy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Portfolio CWV operations.&lt;/strong&gt; Oh Dear documents grouping client sites, read-only access, and branded reports. Agencies that treat Core Web Vitals as the billable discipline still need URL inventory that keeps up with CMS churn, multi-organisation boundaries, and a monitoring spine that assumes PageSpeed quotas rather than minute-level uptime sampling. Stale URL lists look fine while the live template set has moved on. That inventory problem is why we invested in automated discovery rather than assuming someone pastes every new route.&lt;/p&gt;

&lt;p&gt;None of this says Oh Dear is the wrong product. It says the job “uptime + SSL + status pages + daily Lighthouse” and the job “scheduled PSI coverage across a client portfolio” are different purchase decisions. Mixing those jobs on one invoice is where retainer margin usually disappears.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Apogee Watcher optimises for
&lt;/h2&gt;

&lt;p&gt;We optimise for breadth-first PageSpeed monitoring that agencies can run without per-client Google API keys or an uptime product roadmap:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PageSpeed Insights API results stored over time (lab Lighthouse metrics plus CrUX when Google returns field data for the URL).&lt;/li&gt;
&lt;li&gt;Multi-organisation, multi-site structure with Admin, Manager, and Viewer roles.&lt;/li&gt;
&lt;li&gt;Automated page discovery from sitemaps and HTML crawl (see &lt;a href="https://apogeewatcher.com/blog/product-spotlight-how-apogee-watcher-discovers-pages-automatically" rel="noopener noreferrer"&gt;how we discover pages&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Performance budgets and email alerts on scheduled runs (Slack and webhook delivery are on the roadmap; confirm live channels on &lt;a href="https://apogeewatcher.com/features" rel="noopener noreferrer"&gt;features&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Published tiers from Free through Agency on &lt;a href="https://apogeewatcher.com/pricing" rel="noopener noreferrer"&gt;pricing&lt;/a&gt;, with organisation, site, and monthly PageSpeed test quotas pooled at the customer account rather than a surprise per-domain uptime licence for every microsite. Professional is &lt;strong&gt;$79/month&lt;/strong&gt; (25 websites, 2,500 tests/month); Agency is &lt;strong&gt;$199/month&lt;/strong&gt; (unlimited websites, 10,000 tests/month) on the public table at draft time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Gaps we state plainly: no uptime ping product, no public status pages, no SSL certificate monitor as a first-class feature, no Oh Dear-style mixed-content crawler or cron heartbeat suite. When the pager must fire because HTTPS is down at 02:00, keep Oh Dear, Better Stack, or another uptime vendor on that origin. Claiming otherwise would waste a trial week for both sides.&lt;/p&gt;

&lt;p&gt;PDF and white-label report options appear on Professional and Agency on the public pricing table. Confirm what is automated versus manual on &lt;a href="https://apogeewatcher.com/features" rel="noopener noreferrer"&gt;features&lt;/a&gt; before you promise a fully hands-off branded pack in a pitch. Organisation-scoped prospecting for leads is still largely an internal MVP, so do not assume every agency seat can run prospect workflows in-app until that ships.&lt;/p&gt;

&lt;p&gt;For the wider tool taxonomy, use &lt;a href="https://apogeewatcher.com/blog/comparing-pagespeed-monitoring-tools-features-agencies-need" rel="noopener noreferrer"&gt;Comparing PageSpeed Monitoring Tools: Features Agencies Need&lt;/a&gt;. That checklist stays useful after you shortlist Oh Dear or Watcher. It separates measurement jobs from vendor brands without forcing a pairwise winner on every row.&lt;/p&gt;

&lt;h2&gt;
  
  
  Oh Dear vs Apogee Watcher: side-by-side
&lt;/h2&gt;

&lt;p&gt;Use this as a decision grid, not a contract. Verify numbers on each vendor’s site before you sign, and re-check after any plan change. Sticker prices move faster than blog posts.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Topic&lt;/th&gt;
&lt;th&gt;Oh Dear (typical public positioning)&lt;/th&gt;
&lt;th&gt;Apogee Watcher&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Primary job&lt;/td&gt;
&lt;td&gt;Website health: uptime, SSL, DNS, links, status pages, cron, plus performance / Lighthouse&lt;/td&gt;
&lt;td&gt;Multi-tenant PageSpeed Insights + Core Web Vitals monitoring&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Synthetic engine&lt;/td&gt;
&lt;td&gt;Minute-level HTTP uptime; HTTP response-time phases; scheduled Lighthouse scores&lt;/td&gt;
&lt;td&gt;PageSpeed Insights API (Lighthouse lab + CrUX where available)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Real-user / field data&lt;/td&gt;
&lt;td&gt;Not first-party RUM; Lighthouse is lab; HTTP timings are synthetic&lt;/td&gt;
&lt;td&gt;CrUX in PSI results; no first-party RUM&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Entry pricing (public list)&lt;/td&gt;
&lt;td&gt;Solo from **$17/mo** (2 sites); Freelance **$55/mo** (10); Studio **$109/mo** (25); Agency **$165/mo** (50) ([pricing](&lt;a href="https://ohdear.app/pricing)" rel="noopener noreferrer"&gt;https://ohdear.app/pricing)&lt;/a&gt;)&lt;/td&gt;
&lt;td&gt;Free **$0** (1 website); Personal **$9/mo** (1); Starter **$29/mo** (5); Professional **$79/mo** (25); Agency **$199/mo** (unlimited) ([pricing](&lt;a href="https://apogeewatcher.com/pricing)" rel="noopener noreferrer"&gt;https://apogeewatcher.com/pricing)&lt;/a&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Billing drivers&lt;/td&gt;
&lt;td&gt;Sites and servers; all features on every plan&lt;/td&gt;
&lt;td&gt;Organisation, website, and monthly PageSpeed test quota tiers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multi-site / multi-tenant&lt;/td&gt;
&lt;td&gt;Client groups, read-only access, reseller options&lt;/td&gt;
&lt;td&gt;Organisations, sites, pages, RBAC built for agency portfolios&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Page discovery&lt;/td&gt;
&lt;td&gt;Sitemap monitoring among other checks&lt;/td&gt;
&lt;td&gt;Automated sitemap + crawl paths for PageSpeed URL inventory&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Alerts&lt;/td&gt;
&lt;td&gt;Wide notification catalogue (email, Slack, PagerDuty, and more)&lt;/td&gt;
&lt;td&gt;Email today; Slack / webhook per roadmap&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Status pages / SSL / cron&lt;/td&gt;
&lt;td&gt;First-class product features&lt;/td&gt;
&lt;td&gt;Not a Watcher product line&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best day-one use&lt;/td&gt;
&lt;td&gt;Know when sites fail, certificates expire, or status needs an update&lt;/td&gt;
&lt;td&gt;Portfolio PSI monitoring without client-side scripts&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;SpeedCurve and DebugBear occupy the premium synthetic-plus-RUM lane; we compared those separately in &lt;a href="https://apogeewatcher.com/blog/speedcurve-vs-apogee-watcher-agency-multi-tenant" rel="noopener noreferrer"&gt;SpeedCurve vs Apogee Watcher&lt;/a&gt; and &lt;a href="https://apogeewatcher.com/blog/debugbear-vs-apogee-watcher-synthetic-monitoring-multi-site-teams" rel="noopener noreferrer"&gt;DebugBear vs Apogee Watcher&lt;/a&gt;. GTmetrix remains useful for deep lab forensics on one URL; see &lt;a href="https://apogeewatcher.com/blog/gtmetrix-vs-apogee-watcher-pagespeed-monitoring-agencies" rel="noopener noreferrer"&gt;GTmetrix vs Apogee Watcher&lt;/a&gt;. None of those comparisons replace an Oh Dear uptime programme, and none replace portfolio PSI schedules on twenty unrelated CMS stacks.&lt;/p&gt;

&lt;h2&gt;
  
  
  When Oh Dear is the better primary choice
&lt;/h2&gt;

&lt;p&gt;Choose Oh Dear as the primary monitor when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Uptime, SSL expiry, DNS, domain expiry, or public status pages are non-negotiable for the retainer.&lt;/li&gt;
&lt;li&gt;You want one vendor for “is it up?” plus daily Lighthouse scores and HTTP response-time budgets, with every feature unlocked on the plan you buy.&lt;/li&gt;
&lt;li&gt;Clients expect branded status pages or monthly reports that prove independent reachability checks.&lt;/li&gt;
&lt;li&gt;Your team already routes incidents to Slack, PagerDuty, or Opsgenie and needs those destinations on day one.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In those cases an “Oh Dear alternative” search often ends with staying on Oh Dear, or pairing it with a cheaper PageSpeed layer rather than ripping out the uptime suite.&lt;/p&gt;

&lt;h2&gt;
  
  
  When Apogee Watcher is the better Oh Dear alternative for PageSpeed
&lt;/h2&gt;

&lt;p&gt;Choose Watcher as the primary portfolio layer when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The expensive failure mode is Core Web Vitals and PageSpeed regressions across many client hosts, not minute-level downtime alone.&lt;/li&gt;
&lt;li&gt;You need scheduled mobile and desktop PSI runs with CrUX context, without placing RUM snippets or maintaining per-client Google API keys.&lt;/li&gt;
&lt;li&gt;Oh Dear site-capacity pricing for a large roster would fund an uptime bundle you already cover elsewhere, while CWV reporting is still thin.&lt;/li&gt;
&lt;li&gt;Multi-organisation roles, automated discovery, and attention-free triage on domain reports matter more than status-page branding.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Under-$100 agency maths for multi-tenant PSI is covered in &lt;a href="https://apogeewatcher.com/blog/affordable-multi-tenant-performance-monitoring-under-100" rel="noopener noreferrer"&gt;Affordable Multi-Tenant Performance Monitoring Under $100/Month&lt;/a&gt;. Reach for that guide when the budget conversation is the blocker. Reach for this Oh Dear comparison when the blocker is uptime-suite versus CWV-suite fit instead.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to run both (layer, do not replace)
&lt;/h2&gt;

&lt;p&gt;Many agencies should not pick a single winner. Uptime and Core Web Vitals are different jobs that share URLs and quarrel over invoices. A clean split looks like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Keep Oh Dear (or another uptime suite) on money origins for reachability, certificates, and status communication.&lt;/li&gt;
&lt;li&gt;Run Watcher schedules on the same priority URLs for Lighthouse lab history, CrUX-in-PSI field bands, budgets, and portfolio alerts.&lt;/li&gt;
&lt;li&gt;Treat Oh Dear’s HTTP response-time check as an early “origin feels late” signal, then use PSI / CrUX to explain whether users and search actually saw a CWV shift.&lt;/li&gt;
&lt;li&gt;Leave daily Oh Dear Lighthouse on as a lightweight score watchdog if you like the alert destinations; do not pretend it replaces a multi-page PSI programme with discovery.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That is the same “layer, don’t replace” rule we use across the comparison cluster. Rip-and-replace only makes sense when one product already owns the job you are buying. For most retainers, forcing a single vendor to cover both uptime and CWV is how invoices get padded without clearer alerts.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Is Apogee Watcher an Oh Dear alternative?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Yes for PageSpeed and Core Web Vitals portfolio monitoring. No as a drop-in replacement for uptime, SSL, status pages, cron, or DNS monitoring. If those checks are why you opened Oh Dear, keep them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does Oh Dear already do PageSpeed?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Oh Dear runs scheduled Lighthouse audits and HTTP response-time monitoring. That overlaps with “pagespeed” language in buying conversations. It is not the same product shape as continuous PageSpeed Insights portfolio monitoring with CrUX storage, multi-tenant discovery, and CWV budgets across many clients.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How does Oh Dear pricing compare at 25 or 50 sites?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
At draft time, Oh Dear Studio is &lt;strong&gt;$109/month&lt;/strong&gt; for 25 sites and Agency &lt;strong&gt;$165/month&lt;/strong&gt; for 50, with all features included (&lt;a href="https://ohdear.app/pricing" rel="noopener noreferrer"&gt;ohdear.app/pricing&lt;/a&gt;). Watcher Professional is &lt;strong&gt;$79/month&lt;/strong&gt; for 25 websites and 2,500 PageSpeed tests/month; Agency is &lt;strong&gt;$199/month&lt;/strong&gt; for unlimited websites and 10,000 tests/month (&lt;a href="https://apogeewatcher.com/pricing" rel="noopener noreferrer"&gt;apogeewatcher.com/pricing&lt;/a&gt;). Compare apples to apples: Oh Dear’s site price buys the uptime suite; Watcher’s tier buys PSI quota, organisations, and website caps on the same account. Re-check both pages before you sign.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can we use Oh Dear Lighthouse and Watcher together?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Yes. Daily Lighthouse score alerts and portfolio PSI history answer different operational questions. Use Oh Dear when the score drops; use Watcher when you need money-URL inventories, CrUX context, and agency roles across the book of business.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What about free uptime tools instead of Oh Dear?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Free uptime tiers can cover a handful of URLs. They rarely match Oh Dear’s bundled SSL, status pages, and agency reporting story. They also do not solve CWV portfolio monitoring. Stack choices after price filters are in &lt;a href="https://apogeewatcher.com/blog/agency-pagespeed-stacks-2026" rel="noopener noreferrer"&gt;3 Agency PageSpeed Stacks for 2026&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pick the job, then the invoice
&lt;/h2&gt;

&lt;p&gt;If the pager must fire when a client origin is unreachable, start with Oh Dear or another uptime suite and verify &lt;a href="https://ohdear.app/pricing" rel="noopener noreferrer"&gt;Oh Dear pricing&lt;/a&gt; against your site count. If the monthly deck must explain Core Web Vitals across many hosts, start with Watcher’s &lt;a href="https://apogeewatcher.com/pricing" rel="noopener noreferrer"&gt;pricing&lt;/a&gt; and a trial on the money URLs you already report. If both jobs are real, layer them and stop forcing one vendor to pretend it is the other.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://apogeewatcher.com/sign-up" rel="noopener noreferrer"&gt;Start a free Watcher trial&lt;/a&gt; when you want scheduled PageSpeed coverage without ripping out the uptime stack you already trust. For the feature checklist beyond this pairwise split, keep &lt;a href="https://apogeewatcher.com/blog/comparing-pagespeed-monitoring-tools-features-agencies-need" rel="noopener noreferrer"&gt;Comparing PageSpeed Monitoring Tools: Features Agencies Need&lt;/a&gt; open while you shortlist. It remains the taxonomy map after the Oh Dear decision is settled.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://ohdear.app/pricing" rel="noopener noreferrer"&gt;Oh Dear pricing&lt;/a&gt; (Oh Dear)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://ohdear.app/features/performance-monitoring" rel="noopener noreferrer"&gt;Oh Dear performance monitoring&lt;/a&gt; (Oh Dear)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://ohdear.app/features/lighthouse-seo-monitoring" rel="noopener noreferrer"&gt;Oh Dear Lighthouse SEO monitoring&lt;/a&gt; (Oh Dear)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://apogeewatcher.com/pricing" rel="noopener noreferrer"&gt;Apogee Watcher pricing&lt;/a&gt; (Apogee Watcher)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://apogeewatcher.com/blog/comparing-pagespeed-monitoring-tools-features-agencies-need" rel="noopener noreferrer"&gt;Comparing PageSpeed Monitoring Tools: Features Agencies Need&lt;/a&gt; (Apogee Watcher)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://apogeewatcher.com/blog/when-to-use-synthetic-vs-real-user-monitoring-performance" rel="noopener noreferrer"&gt;When to Use Synthetic vs Real User Monitoring for Performance&lt;/a&gt; (Apogee Watcher)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://apogeewatcher.com/blog/agency-pagespeed-stacks-2026" rel="noopener noreferrer"&gt;3 Agency PageSpeed Stacks for 2026&lt;/a&gt; (Apogee Watcher)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://apogeewatcher.com/blog/affordable-multi-tenant-performance-monitoring-under-100" rel="noopener noreferrer"&gt;Affordable Multi-Tenant Performance Monitoring Under $100/Month&lt;/a&gt; (Apogee Watcher)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://apogeewatcher.com/blog/speedcurve-vs-apogee-watcher-agency-multi-tenant" rel="noopener noreferrer"&gt;SpeedCurve vs Apogee Watcher&lt;/a&gt; (Apogee Watcher)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://apogeewatcher.com/blog/debugbear-vs-apogee-watcher-synthetic-monitoring-multi-site-teams" rel="noopener noreferrer"&gt;DebugBear vs Apogee Watcher&lt;/a&gt; (Apogee Watcher)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://apogeewatcher.com/blog/gtmetrix-vs-apogee-watcher-pagespeed-monitoring-agencies" rel="noopener noreferrer"&gt;GTmetrix vs Apogee Watcher&lt;/a&gt; (Apogee Watcher)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://apogeewatcher.com/blog/product-spotlight-how-apogee-watcher-discovers-pages-automatically" rel="noopener noreferrer"&gt;How Apogee Watcher discovers pages automatically&lt;/a&gt; (Apogee Watcher)&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>webperf</category>
      <category>seo</category>
    </item>
    <item>
      <title>robots.txt, llms.txt, and cats.txt are not the same job</title>
      <dc:creator>Apogee Watcher</dc:creator>
      <pubDate>Mon, 21 Sep 2026 20:39:27 +0000</pubDate>
      <link>https://dev.to/apogeewatcher/robotstxt-llmstxt-and-catstxt-are-not-the-same-job-1gee</link>
      <guid>https://dev.to/apogeewatcher/robotstxt-llmstxt-and-catstxt-are-not-the-same-job-1gee</guid>
      <description>&lt;p&gt;Three text files keep showing up in the same AI SEO slide. They share a root path and a &lt;code&gt;.txt&lt;/code&gt; extension, and that is almost all they share.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;robots.txt&lt;/code&gt; states which paths a given crawler may fetch. &lt;code&gt;llms.txt&lt;/code&gt; is an optional Markdown map that helps agents find curated pages when they choose to look. &lt;code&gt;cats.txt&lt;/code&gt; was invented as satire, yet it still cleared the same “proofs” people use to sell the second file: bots fetched it, Google indexed it, models repeated it, and ChatGPT endorsed it. If those observations prove a protocol, they also prove your office cat is a ranking factor. Adding all three and calling the stack complete does not answer the client brief. The work is clearer when you name which job you are buying before you invoice it, then match the artefact to that job.&lt;/p&gt;

&lt;h2&gt;
  
  
  What robots.txt actually controls
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;robots.txt&lt;/code&gt; is the long-standing Robots Exclusion Protocol file at the site root. Compliant crawlers read user-agent rules, &lt;code&gt;Allow&lt;/code&gt; / &lt;code&gt;Disallow&lt;/code&gt; paths, and often a sitemap pointer. Google’s own &lt;a href="https://developers.google.com/search/docs/crawling-indexing/robots/intro" rel="noopener noreferrer"&gt;robots.txt guide&lt;/a&gt; is blunt about the limits: the file guides crawl behaviour, but it is not a security boundary, and it is not a reliable way to keep a URL out of Google Search if other sites link to it. For that you need &lt;code&gt;noindex&lt;/code&gt;, authentication, or removal.&lt;/p&gt;

&lt;p&gt;For AI crawlers, the same file is still the control that well-behaved bots document. OpenAI’s GPTBot, Anthropic’s crawlers, and similar agents that honour REP will respect a &lt;code&gt;Disallow&lt;/code&gt; aimed at their user-agent. That does not mean every scraper is polite, and it does not mean a disallowed URL vanishes from every index, but it does mean crawl preference lives here, not in a Markdown wishlist.&lt;/p&gt;

&lt;p&gt;If the ticket is “stop this bot hammering &lt;code&gt;/api&lt;/code&gt;” or “leave staging alone”, you are in &lt;code&gt;robots.txt&lt;/code&gt; territory. Speed and timeouts still matter once a bot is allowed, because a crawler that times out on a shell page never reaches the content you hoped it would quote. We wrote up that fetch foundation in &lt;a href="https://apogeewatcher.com/blog/why-ai-crawlers-need-fast-crawlable-pages-and-how-to-stay-ready?utm_source=hashnode&amp;amp;utm_medium=referral&amp;amp;utm_campaign=robots-txt-llms-txt-cats-txt" rel="noopener noreferrer"&gt;Why AI Crawlers Need Fast, Crawlable Pages&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What llms.txt is for (and is not)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://llmstxt.org/" rel="noopener noreferrer"&gt;llms.txt&lt;/a&gt; is Jeremy Howard’s proposal for a Markdown overview at &lt;code&gt;/llms.txt&lt;/code&gt; (or under a path such as &lt;code&gt;/docs/llms.txt&lt;/code&gt;). The format is deliberately simple: a site title, a short summary, then headed lists of links to cleaner markdown versions of important pages. The pitch is orientation for agents that need a small, curated entry point, especially on documentation sites where coding agents waste tokens on nav chrome.&lt;/p&gt;

&lt;p&gt;It does not grant or deny crawl access, and it does not replace &lt;code&gt;robots.txt&lt;/code&gt;, &lt;code&gt;sitemap.xml&lt;/code&gt;, or structured data. Google’s &lt;a href="https://developers.google.com/search/docs/appearance/ai-features" rel="noopener noreferrer"&gt;AI features documentation&lt;/a&gt; says you do not need new machine-readable AI text files or markup to appear in AI Overviews or AI Mode, and that there are no extra technical requirements beyond ordinary Search eligibility. Google does not document &lt;code&gt;llms.txt&lt;/code&gt; as a ranking or inclusion control for those features, so if the business case is “rank better in Google’s generative results”, this file is not the lever to buy.&lt;/p&gt;

&lt;p&gt;Lighthouse’s experimental Agentic Browsing category can still check for an &lt;code&gt;llms.txt&lt;/code&gt; as a discoverability signal for agents. That is a tooling conversation, not a Search ranking claim. We go through the scoring and what to monitor in &lt;a href="https://apogeewatcher.com/blog/lighthouse-agentic-browsing-scoring?utm_source=hashnode&amp;amp;utm_medium=referral&amp;amp;utm_campaign=robots-txt-llms-txt-cats-txt" rel="noopener noreferrer"&gt;Lighthouse Agentic Browsing: How to rank in chatbots&lt;/a&gt;. Shipping the file because an audit row went amber is a product decision. Shipping it because a deck promised ChatGPT citations is a different claim, and it needs different evidence.&lt;/p&gt;

&lt;h2&gt;
  
  
  What cats.txt proved about “evidence”
&lt;/h2&gt;

&lt;p&gt;Mark Williams-Cook published &lt;code&gt;cats.txt&lt;/code&gt; as a joke standard: declare your office cats, job titles, and a &lt;code&gt;PurrLevel&lt;/code&gt;. He was not proposing taxonomy for chatbots. He was showing that the industry’s favourite proofs for &lt;code&gt;llms.txt&lt;/code&gt; also certified nonsense. Bots crawled the file, Google indexed it, and models returned cat biographies that existed only in that text. ChatGPT, for a while, cheerfully recommended &lt;code&gt;cats.txt&lt;/code&gt; as a ranking tactic, then later converged on “it is a joke” once the surrounding web said so.&lt;/p&gt;

&lt;p&gt;Keep the lesson, not the file. A fetch in the logs means a crawler requested a URL; an indexed &lt;code&gt;.txt&lt;/code&gt; means Google found words at a URL. An LLM repeating a fact means retrieval found a page that ranked, and a model endorsing a tactic means the training and chat corpus is full of people selling that tactic. None of those observations, on their own, prove that a consumer chatbot honours a special protocol when it answers a user. &lt;code&gt;cats.txt&lt;/code&gt; does not belong on a client delivery checklist, but it is useful in a training deck when someone treats crawl, index, and chat echo as proof of GEO impact.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three files, three jobs
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Artefact&lt;/th&gt;
&lt;th&gt;Job&lt;/th&gt;
&lt;th&gt;Who is expected to care&lt;/th&gt;
&lt;th&gt;Enforcement&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;robots.txt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;State crawl preferences per user-agent&lt;/td&gt;
&lt;td&gt;Search and AI crawlers that honour REP&lt;/td&gt;
&lt;td&gt;Soft: polite bots obey; hostile bots may not&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;llms.txt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Optional curated map for agents / docs&lt;/td&gt;
&lt;td&gt;Systems that choose to fetch and parse it&lt;/td&gt;
&lt;td&gt;None as access control; not a documented Google Search ranking input&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;cats.txt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Satire of weak GEO “proofs”&lt;/td&gt;
&lt;td&gt;Nobody as a real protocol&lt;/td&gt;
&lt;td&gt;N/A: teaching tool, not a standard to implement&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A sitemap still lists indexable URLs for discovery, and schema still describes entities on the page. Neither becomes redundant because someone published a new root file with a catchy name. Those older artefacts still do discovery and meaning work that a Markdown map cannot replace on its own.&lt;/p&gt;

&lt;h2&gt;
  
  
  Which file earns the ticket this week
&lt;/h2&gt;

&lt;p&gt;A clearer ticket starts from the outcome the client named, not from a template that lists every root-path &lt;code&gt;.txt&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;Crawl control for GPTBot, Googlebot, or a CDN bot-management policy still belongs in &lt;code&gt;robots.txt&lt;/code&gt;, with a check in the logs that the right user-agent rules are live. An &lt;code&gt;llms.txt&lt;/code&gt; can be low-cost housekeeping when agents and coding tools need a short map of docs, especially on documentation hosts that generate one automatically. “Proof that AI search will cite us because a &lt;code&gt;.txt&lt;/code&gt; exists” is a different brief, and it needs a different success metric. Citation and answer inclusion still depend on crawlability, content quality, and retrieval, not on inventing a parallel exclusion file.&lt;/p&gt;

&lt;p&gt;Agencies inherit another failure mode: shipping every trendy file so the audit screenshot looks complete. Three green checkmarks for three unrelated jobs is not a strategy. A clearer setup is one owner for crawl rules, one decision on whether an agent map is worth maintaining, and no claim that satire is a ranking lever.&lt;/p&gt;

&lt;p&gt;For teams who still want AI-search visibility without buying a GEO SaaS stack, the useful checks stay ordinary. Performance and crawl health on the money pages matter more than another root file, and a shortlist of URLs worth defending helps when a client asks why a chatbot ignored them. We outline that path in &lt;a href="https://apogeewatcher.com/blog/ai-search-optimization-monitor-without-subscription?utm_source=hashnode&amp;amp;utm_medium=referral&amp;amp;utm_campaign=robots-txt-llms-txt-cats-txt" rel="noopener noreferrer"&gt;AI Search Optimization: What to Monitor without a subscription&lt;/a&gt;.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Does Google Search use llms.txt?
&lt;/h3&gt;

&lt;p&gt;Google does not document &lt;code&gt;llms.txt&lt;/code&gt; as a requirement or ranking input for AI Overviews or AI Mode. The current AI features guidance says you do not need new machine-readable AI text files or markup to appear in those experiences, and ordinary Search eligibility is enough for those features.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is llms.txt a replacement for robots.txt?
&lt;/h3&gt;

&lt;p&gt;No. &lt;code&gt;robots.txt&lt;/code&gt; expresses crawl preferences; &lt;code&gt;llms.txt&lt;/code&gt; orients agents that fetch it. Mixing the two in one “AI robots” story confuses access control with a documentation index.&lt;/p&gt;

&lt;h3&gt;
  
  
  Should we add cats.txt?
&lt;/h3&gt;

&lt;p&gt;Only if you want the joke on purpose. It is useful in training decks to show why crawl-plus-index-plus-chat-echo is a weak proof, but it is not a production SEO control.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does Lighthouse requiring llms.txt mean Google Search requires it?
&lt;/h3&gt;

&lt;p&gt;No. Lighthouse’s Agentic Browsing checks are a separate product surface, so an audit row about discoverability for agents is not a Search ranking requirement.&lt;/p&gt;

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

&lt;p&gt;Before the next AI SEO sprint, a useful ticket line is one sentence naming the job: crawl preference, agent orientation, or citation proof. The artefact should match that sentence. Fetch success, Core Web Vitals, and whether money pages stay fast enough for humans and bots still move the outcomes clients notice.&lt;/p&gt;

&lt;p&gt;If you want that measurement on a multi-site portfolio without a separate GEO product, &lt;a href="https://apogeewatcher.com/sign-up?utm_source=hashnode&amp;amp;utm_medium=referral&amp;amp;utm_campaign=robots-txt-llms-txt-cats-txt" rel="noopener noreferrer"&gt;start a Watcher trial&lt;/a&gt; or &lt;a href="https://apogeewatcher.com/check?utm_source=hashnode&amp;amp;utm_medium=referral&amp;amp;utm_campaign=robots-txt-llms-txt-cats-txt" rel="noopener noreferrer"&gt;run a free domain scan&lt;/a&gt;.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://developers.google.com/search/docs/crawling-indexing/robots/intro" rel="noopener noreferrer"&gt;Robots.txt Introduction and Guide&lt;/a&gt; (Google Search Central)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developers.google.com/search/docs/appearance/ai-features" rel="noopener noreferrer"&gt;AI features and your website&lt;/a&gt; (Google Search Central)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://llmstxt.org/" rel="noopener noreferrer"&gt;The /llms.txt file, v2&lt;/a&gt; (Jeremy Howard / Answer.AI)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://markwilliamscook.substack.com/p/how-catstxt-showed-llmstxt-evidence" rel="noopener noreferrer"&gt;How cats.txt showed llms.txt evidence is GEO astrology&lt;/a&gt; (Mark Williams-Cook)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://catstxt.org/" rel="noopener noreferrer"&gt;The cats.txt standard&lt;/a&gt; (satirical companion site)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.chrome.com/docs/lighthouse/agentic-browsing/scoring" rel="noopener noreferrer"&gt;Lighthouse agentic browsing scoring&lt;/a&gt; (Chrome Developers)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://apogeewatcher.com/blog/why-ai-crawlers-need-fast-crawlable-pages-and-how-to-stay-ready" rel="noopener noreferrer"&gt;Why AI Crawlers Need Fast, Crawlable Pages&lt;/a&gt; (Apogee Watcher)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://apogeewatcher.com/blog/lighthouse-agentic-browsing-scoring" rel="noopener noreferrer"&gt;Lighthouse Agentic Browsing: How to rank in chatbots&lt;/a&gt; (Apogee Watcher)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://apogeewatcher.com/blog/ai-search-optimization-monitor-without-subscription" rel="noopener noreferrer"&gt;AI Search Optimization: What to Monitor without a subscription&lt;/a&gt; (Apogee Watcher)&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>seo</category>
      <category>webdev</category>
      <category>webperf</category>
      <category>agency</category>
    </item>
    <item>
      <title>Core Web Vitals Benchmarks for Magento Stores (2026 Data)</title>
      <dc:creator>Apogee Watcher</dc:creator>
      <pubDate>Sun, 20 Sep 2026 07:58:52 +0000</pubDate>
      <link>https://dev.to/apogeewatcher/core-web-vitals-benchmarks-for-magento-stores-2026-data-9in</link>
      <guid>https://dev.to/apogeewatcher/core-web-vitals-benchmarks-for-magento-stores-2026-data-9in</guid>
      <description>&lt;p&gt;Public Magento Core Web Vitals tables often put Adobe Commerce in the middle of the ecommerce pack: roughly four to five in ten Magento origins pass all three vitals on mobile CrUX, depending on who measured and how they labelled the platform. Open a multi-page Lighthouse sample on real Magento storefronts and the picture changes around Largest Contentful Paint. Mobile Performance averages sit near the high 50s, lab LCP medians stretch well past Google's 2.5 s “good” line, and unused JavaScript shows up on almost every domain. Both views can be true. Population CrUX describes popular origins under field conditions. Portfolio monitoring needs URL-level and multi-page evidence, because catalog templates, checkout, and extension scripts decide what shoppers feel.&lt;/p&gt;

&lt;p&gt;What follows separates those clocks, publishes a reproducible sample from Magento users we analyse in Apogee Watcher after a strong-signal platform check, and points at the remediation work that actually moves scores. The method matches our &lt;a href="https://apogeewatcher.com/blog/core-web-vitals-benchmarks-for-shopify-stores-2026-data" rel="noopener noreferrer"&gt;Shopify Core Web Vitals benchmarks for 2026&lt;/a&gt;. For ecommerce metric priorities beyond the three vitals, pair this with &lt;a href="https://apogeewatcher.com/blog/ecommerce-performance-monitoring-what-metrics-matter" rel="noopener noreferrer"&gt;Performance Monitoring for E-Commerce: What Metrics Matter Most&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What counts as a reliable Magento Core Web Vitals benchmark in 2026
&lt;/h2&gt;

&lt;p&gt;For Core Web Vitals, the strongest public field source remains the Chrome UX Report (CrUX). Google's methodology is clear about inclusion: pages and origins must be publicly discoverable and popular enough, data comes from eligible Chrome users, and thresholds are read at the 75th percentile over a rolling window. That is why Search Console and the field section of PageSpeed Insights matter for ranking and real-user claims, while a single Lighthouse run remains a diagnostic tool.&lt;/p&gt;

&lt;p&gt;Google's published thresholds are unchanged for the three metrics:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Good (p75)&lt;/th&gt;
&lt;th&gt;Needs improvement&lt;/th&gt;
&lt;th&gt;Poor&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;2.5 s – 4.0 s&lt;/td&gt;
&lt;td&gt;&amp;gt; 4.0 s&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;200 ms – 500 ms&lt;/td&gt;
&lt;td&gt;&amp;gt; 500 ms&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;0.1 – 0.25&lt;/td&gt;
&lt;td&gt;&amp;gt; 0.25&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;An origin or URL group passes Core Web Vitals when all three sit in the good bucket at p75. A Lighthouse Performance score is a different artefact: it blends lab timings under a throttled environment and is useful for regression detection, not as a substitute for CrUX pass/fail. If you need a refresher on the three metrics themselves, start with &lt;a href="https://apogeewatcher.com/blog/what-are-core-web-vitals-a-practical-guide-for-2026" rel="noopener noreferrer"&gt;What Are Core Web Vitals? A Practical Guide for 2026&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A useful Magento benchmark therefore states four things up front: which clock (CrUX field versus Lighthouse lab), which URLs (homepage only versus category, PDP, cart, checkout), how scores are aggregated (single URL versus median or mean across pages), and the collection window. Platform marketing and vendor health reports often quote pass rates without that scaffolding. Agencies managing twenty Magento clients need the scaffolding more than another green screenshot.&lt;/p&gt;

&lt;p&gt;Sources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.chrome.com/docs/crux/methodology" rel="noopener noreferrer"&gt;CrUX methodology&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developers.google.com/search/docs/appearance/core-web-vitals" rel="noopener noreferrer"&gt;Understanding Core Web Vitals and Google search results&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Multi-page lab sample from Watcher's verified Magento users
&lt;/h2&gt;

&lt;p&gt;We keep Magento and Adobe Commerce storefronts in Watcher and run multi-page PageSpeed Insights analyses that store Lighthouse lab metrics and CrUX field payloads when Google returns them. For this snapshot we took the latest domain report per Magento-verified user after a strong-signal platform check (n = 76 stores with aggregated reports; 80 users carried the verified Magento tag; reports generated between late August and mid-September 2026). Verification requires Magento-specific evidence such as &lt;code&gt;x-magento-*&lt;/code&gt; headers, &lt;code&gt;Magento_&lt;/code&gt; modules, &lt;code&gt;text/x-magento-init&lt;/code&gt;, Magento cookies, or &lt;code&gt;/static/version&lt;/code&gt; together with &lt;code&gt;form_key&lt;/code&gt;. Loose strings that falsely labelled Next.js and Salesforce Commerce Cloud sites as Magento were excluded.&lt;/p&gt;

&lt;p&gt;Each report averages Lighthouse metrics across the URLs selected for that domain (median 13 analysed pages per store; 1,195 page runs in total). Values below are store-level averages of lab runs, not single-URL CrUX p75s, so a store that looks healthy on one PDP can still drag the average when cart and category templates are included.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mobile and desktop Lighthouse Performance
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjaisru5yg4mi0g8d4y40.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjaisru5yg4mi0g8d4y40.webp" alt="Grouped bar chart of Magento verified users Lighthouse Performance store averages for mobile and desktop across min, P25, median, P75, max, and mean (n=76), with a Perf ≥ 90 reference line" width="799" height="478"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Slice&lt;/th&gt;
&lt;th&gt;Mobile Performance (avg)&lt;/th&gt;
&lt;th&gt;Desktop Performance (avg)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Minimum&lt;/td&gt;
&lt;td&gt;27&lt;/td&gt;
&lt;td&gt;39&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;25th percentile&lt;/td&gt;
&lt;td&gt;43&lt;/td&gt;
&lt;td&gt;62&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Median&lt;/td&gt;
&lt;td&gt;58&lt;/td&gt;
&lt;td&gt;75&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;75th percentile&lt;/td&gt;
&lt;td&gt;70&lt;/td&gt;
&lt;td&gt;87&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Maximum&lt;/td&gt;
&lt;td&gt;93&lt;/td&gt;
&lt;td&gt;98&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mean&lt;/td&gt;
&lt;td&gt;58&lt;/td&gt;
&lt;td&gt;74&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Half of the sample sits at or below a mobile Performance average of about 58. Forty-eight of 76 stores clear a mobile average of 50, 19 of 76 clear 70, and only 1 of 76 store averages reached 90 on mobile. Desktop is kinder in the same runs (median about 75), which matches what agencies see when a client forwards a desktop-only screenshot and assumes the site is fine. Compared with our Shopify Watcher sample (median mobile Performance about 51 on 64 stores), this Magento set lands a little higher on the Performance dial while still failing Google's lab-friendly Performance ≥ 90 bar almost everywhere. The shared pattern matters more than the six-point gap: multi-page Magento lab averages remain a remediation queue, not proof that the storefront is done.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mobile lab Core Web Vitals timings (store averages)
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Median&lt;/th&gt;
&lt;th&gt;75th percentile&lt;/th&gt;
&lt;th&gt;Notes in this sample&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;LCP (s)&lt;/td&gt;
&lt;td&gt;8.2&lt;/td&gt;
&lt;td&gt;12.6&lt;/td&gt;
&lt;td&gt;2 / 76 store averages ≤ 2.5 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;INP (s)&lt;/td&gt;
&lt;td&gt;0.22&lt;/td&gt;
&lt;td&gt;0.30&lt;/td&gt;
&lt;td&gt;34 / 76 store averages ≤ 0.20 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CLS&lt;/td&gt;
&lt;td&gt;0.027&lt;/td&gt;
&lt;td&gt;0.064&lt;/td&gt;
&lt;td&gt;63 / 76 store averages ≤ 0.1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;CLS is often already in a good lab band even when LCP is not. LCP is the structural problem. Multi-page mobile averages in the 6–13 s range do not mean every URL fails CrUX at that severity, but they do mean Lighthouse is consistently flagging heavy LCP candidates across templates. That is the signal agencies should take into a remediation backlog before arguing about a two-point Performance score change.&lt;/p&gt;

&lt;h3&gt;
  
  
  CrUX origin categories when field data exists
&lt;/h3&gt;

&lt;p&gt;Not every user has origin-level CrUX on the report. Where mobile origin overall category was present (n = 46), we saw 15 FAST, 18 AVERAGE, and 13 SLOW. Origin LCP was FAST on 35 of those stores, INP FAST on 41, and CLS FAST on 39. Field data is often healthier than multi-page lab averages on the same domains, especially for LCP and INP, because lab throttling and averaging across many templates punish media-heavy PDPs that may still pass origin-level CrUX when popular URLs are lighter.&lt;/p&gt;

&lt;h3&gt;
  
  
  Recurring Lighthouse opportunities
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffdy6h8sc601fqu3ugfbk.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffdy6h8sc601fqu3ugfbk.webp" alt="Horizontal bar chart of recurring mobile Lighthouse opportunities across 76 Magento stores, led by unused JavaScript 72/76 and unused CSS 66/76" width="800" height="419"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Across the 76 latest reports, the most common mobile opportunities were:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Opportunity&lt;/th&gt;
&lt;th&gt;Stores where it appeared&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Reduce unused JavaScript&lt;/td&gt;
&lt;td&gt;72 / 76&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reduce unused CSS&lt;/td&gt;
&lt;td&gt;66 / 76&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Avoid multiple page redirects&lt;/td&gt;
&lt;td&gt;38 / 76&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Minify JavaScript&lt;/td&gt;
&lt;td&gt;26 / 76&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Initial server response time&lt;/td&gt;
&lt;td&gt;13 / 76&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Minify CSS&lt;/td&gt;
&lt;td&gt;8 / 76&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Unused JavaScript is effectively the default Magento finding in this sample. Theme and UI component code, extension scripts, analytics, and personalisation layers compete for the same main thread that INP and Total Blocking Time care about. Redirect chains still show up on enough domains to deserve a separate checklist item when agencies inherit migrated catalogs or multi-store URL maps.&lt;/p&gt;

&lt;h3&gt;
  
  
  Attention-free score across the Magento sample
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjw6po601uvfftph4kkhn.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjw6po601uvfftph4kkhn.webp" alt="Two charts of Magento Attention-Free Score for 76 verified users: distribution percentiles with median 4%, and store counts by band including 34 at 0% and 0 at 100%" width="800" height="417"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Performance averages answer “how green is the typical page?”. The &lt;a href="https://apogeewatcher.com/blog/attention-free-score-domain-report-summary" rel="noopener noreferrer"&gt;Attention-Free Score&lt;/a&gt; on Watcher domain reports answers a stricter triage question: what share of completed page×device tests pass all lab gates at once (Performance ≥ 90, Accessibility / Best Practices / SEO ≥ 80, LCP ≤ 2.5 s, CLS ≤ 0.1, INP ≤ 0.2 s with Total Blocking Time as a fallback when INP is missing). One hundred percent means no page needs attention on either strategy.&lt;/p&gt;

&lt;p&gt;We computed that score for the same 76 latest Magento reports:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Slice&lt;/th&gt;
&lt;th&gt;Attention-free %&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Minimum&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;25th percentile&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Median&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;75th percentile&lt;/td&gt;
&lt;td&gt;17&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Maximum&lt;/td&gt;
&lt;td&gt;71&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mean&lt;/td&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;None of the 76 stores reached 100%. Only two cleared 50% (paradoxlabs.com at 71% and evrig.com at 61%). Thirty-four sat at 0%, and 49 were under 10%. Across every completed test in the cohort (2,325 page×device runs), only 12% were fully clear. Summary status landed on “Attention recommended” for 74 stores and “Watch” for the other two; none were a clean “Pass”.&lt;/p&gt;

&lt;p&gt;The most common top gap on the failing scoreboard was Performance (66 stores). That aligns with the multi-page averages above: a median mobile Performance of 58 can coexist with almost every store failing the Perf ≥ 90 gate on most templates, especially once LCP ≤ 2.5 s is required in the same pass/fail set. Agencies get clearer decisions when they read Attention-Free as the portfolio triage dial and CrUX as the ranking dial, rather than treating the two as substitutes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Magento Core Web Vitals still vary store to store
&lt;/h2&gt;

&lt;p&gt;Two shops on Magento 2 / Adobe Commerce can land in different buckets for reasons that never appear in a platform marketing page:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Extension footprint. Reviews, loyalty, chat, configurators, and A/B tools add script weight on category and PDP templates.&lt;/li&gt;
&lt;li&gt;Frontend stack. Luma-era RequireJS bundles, Hyvä, custom headless storefronts, and heavy page builders change what Lighthouse sees even when the catalog is identical.&lt;/li&gt;
&lt;li&gt;Media strategy. Hero video, large product galleries, and unprioritised LCP images dominate mobile LCP in lab runs.&lt;/li&gt;
&lt;li&gt;Template mix. A clean homepage can hide a slow cart drawer or a script-heavy layered navigation when you only test one URL.&lt;/li&gt;
&lt;li&gt;Caching and TTFB. Full-page cache hits versus misses, Varnish/CDN configuration, and cold admin-side caches change first-byte timings that then delay LCP.&lt;/li&gt;
&lt;li&gt;Traffic shape and geography. CrUX inclusion and p75 values move with real visitor mix; lab runs do not.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Platform-level medians help set expectations in a roadmap review, but they do not replace scheduled checks on the URLs that drive revenue. Population CrUX tables stay useful as context; multi-page samples are the day-to-day view we use when an agency asks which Magento client to fix first.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lab Lighthouse scores versus CrUX field data on Magento
&lt;/h2&gt;

&lt;p&gt;Reporting stays clearer when lab and field stay in separate columns:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Question&lt;/th&gt;
&lt;th&gt;Prefer&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Does Google’s page experience view look healthy?&lt;/td&gt;
&lt;td&gt;CrUX / Search Console / PSI field (p75)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Did last week’s release or extension change regress templates?&lt;/td&gt;
&lt;td&gt;Scheduled Lighthouse (lab), same URL set&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Are we comparing to a platform CrUX table?&lt;/td&gt;
&lt;td&gt;Population studies with stated n and month&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Are we comparing agency client A to client B?&lt;/td&gt;
&lt;td&gt;Same tool, same URL roles, same aggregation&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Watcher domain reports already separate lab score cards from field methodology notes (median of URL-level p75s where present, origin badge when available). That separation belongs in client decks too. A green origin badge with a mobile Performance average of 45 is not a contradiction; it is a prompt to inspect which templates the lab average is punishing. For portfolio monitoring design, see &lt;a href="https://apogeewatcher.com/blog/core-web-vitals-monitoring-checklist-for-agencies" rel="noopener noreferrer"&gt;Core Web Vitals Monitoring Checklist for Agencies&lt;/a&gt; and &lt;a href="https://apogeewatcher.com/blog/how-to-set-up-automated-pagespeed-monitoring" rel="noopener noreferrer"&gt;How to Set Up Automated PageSpeed Monitoring&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to fix first when Magento Lighthouse opportunities repeat
&lt;/h2&gt;

&lt;p&gt;When unused JavaScript and unused CSS dominate the opportunity list, a useful starting set is the money path (home, top category, top PDP, cart, checkout) rather than a homepage-only screenshot contest:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Measure the same URLs on a schedule. Lab averages move when discovery adds templates, so locking the set before debating a three-point Performance change keeps the comparison honest.&lt;/li&gt;
&lt;li&gt;Attack LCP candidates on the worst templates first. Hero and primary product imagery, font loading, and above-the-fold critical CSS usually repay the work; lazy-loading the LCP image is a common Magento misstep.&lt;/li&gt;
&lt;li&gt;Shrink the extension and theme JavaScript budget. Removing unused modules, deferring non-critical RequireJS components, and challenging each chat or review widget on PDP reduces the unused-JS finding that dominates this sample.&lt;/li&gt;
&lt;li&gt;Check redirects and HTML caching. Multi-hop store codes, trailing-slash policies, and cold full-page cache misses show up as redirects or slow document response before paint work begins.&lt;/li&gt;
&lt;li&gt;Reconcile with CrUX monthly. If origin field data is FAST while lab LCP is ugly, document which templates are lab-only pain and which URLs Search Console actually groups.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Trimmed Magento storefronts in our sample can still clear mobile lab averages in the mid-80s to low-90s (for example jajuma.de, loviux.com, and paradoxlabs.com in this pull). Heavier catalogs and extension stacks land in the high 20s to mid-30s with lab LCP well into double-digit seconds. The platform label is the same; the implementation load is not.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to run a repeatable Magento CWV cohort each month
&lt;/h2&gt;

&lt;p&gt;A monthly Magento cohort holds up better when the origin list and URL roles stay fixed:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Keep a fixed list of Magento / Adobe Commerce origins (clients plus any public cohort you track).&lt;/li&gt;
&lt;li&gt;Run the same multi-page URL roles every month (home, category, PDP, cart, checkout when reachable).&lt;/li&gt;
&lt;li&gt;Publish store-level lab averages and, separately, origin CrUX categories when present.&lt;/li&gt;
&lt;li&gt;Track unused JavaScript and unused CSS occurrence counts so extension creep is visible.&lt;/li&gt;
&lt;li&gt;Annotate releases: Magento upgrades, Hyvä or theme changes, extension adds, CDN or FPC changes, and major catalog campaigns.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That schedule turns a one-off benchmark into a monitoring habit. If you want the same workflow without rebuilding spreadsheets, &lt;a href="https://apogeewatcher.com/check" rel="noopener noreferrer"&gt;start a free Watcher check&lt;/a&gt; or &lt;a href="https://apogeewatcher.com/sign-up" rel="noopener noreferrer"&gt;create an account&lt;/a&gt; and schedule the money-path URLs you already care about. The charts and tables above are a September 2026 snapshot; the monthly loop is what keeps Magento CWV from becoming another stale slide.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;What is a good Magento Core Web Vitals score in 2026?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
For ranking and real-user claims, use CrUX or Search Console at p75: LCP ≤ 2.5 s, INP ≤ 200 ms, CLS ≤ 0.1. Lighthouse Performance averages in the 50s are common on multi-page Magento lab samples and are not a CrUX pass/fail substitute.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why is Magento LCP so high in lab tests?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Throttled Lighthouse plus heavy heroes, product media, and JavaScript-heavy templates inflate store averages when many URLs are included. Origin CrUX can still look healthier if popular URLs are lighter than the full template set.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do Magento stores usually pass Core Web Vitals in the field?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Population studies in mid-2026 place Magento all-CWV mobile pass rates roughly in the 40–52% range depending on the dataset. That is orientation only; your client's origin is the scoreboard that matters.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is unused JavaScript inevitable on Magento?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
It is extremely common in our sample (72 / 76 stores), but it is not inevitable. Extension audits, lighter frontends, and deferred non-critical scripts reduce the finding. Count scripts on money-path templates before accepting “Magento is just heavy” as the final answer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How does this compare with Shopify?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Our Shopify Watcher sample (n = 64) showed a median mobile Performance of about 51 with unused JavaScript on 61 of 64 stores. This Magento sample (n = 76) shows a median about 58, with unused JavaScript on 72 of 76. LCP remains the hard lab problem on both platforms. Compare like with like: same clocks, same multi-page aggregation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Should we migrate off Magento for Core Web Vitals?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Not based on a lab average alone. Fix LCP candidates, extension weight, and caching first; re-measure the same URL set; then decide whether a frontend rebuild or platform change is the cheaper path for that catalog.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What does an Attention-Free Score near 0% mean for Magento?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
It means almost every completed mobile and desktop test failed at least one lab gate, usually Performance ≥ 90 and/or LCP ≤ 2.5 s. It does not mean origin CrUX is automatically Poor. Attention-Free helps prioritise templates; Search Console or PSI field data supports ranking claims.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://developer.chrome.com/docs/crux/methodology" rel="noopener noreferrer"&gt;CrUX methodology&lt;/a&gt; (Chrome Developers)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developers.google.com/search/docs/appearance/core-web-vitals" rel="noopener noreferrer"&gt;Understanding Core Web Vitals and Google search results&lt;/a&gt; (Google Search Central)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://apogeewatcher.com/blog/core-web-vitals-benchmarks-for-shopify-stores-2026-data" rel="noopener noreferrer"&gt;Core Web Vitals Benchmarks for Shopify Stores (2026 Data)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://apogeewatcher.com/blog/attention-free-score-domain-report-summary" rel="noopener noreferrer"&gt;Attention-Free Score: How Domain Reports Show Which Pages Need Work&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://apogeewatcher.com/blog/what-are-core-web-vitals-a-practical-guide-for-2026" rel="noopener noreferrer"&gt;What Are Core Web Vitals? A Practical Guide for 2026&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://apogeewatcher.com/blog/ecommerce-performance-monitoring-what-metrics-matter" rel="noopener noreferrer"&gt;Performance Monitoring for E-Commerce: What Metrics Matter Most&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://apogeewatcher.com/blog/core-web-vitals-monitoring-checklist-for-agencies" rel="noopener noreferrer"&gt;Core Web Vitals Monitoring Checklist for Agencies&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://apogeewatcher.com/blog/how-to-set-up-automated-pagespeed-monitoring" rel="noopener noreferrer"&gt;How to Set Up Automated PageSpeed Monitoring&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>webperf</category>
      <category>seo</category>
    </item>
    <item>
      <title>Affordable Multi-Tenant Performance Monitoring Under $100/Month</title>
      <dc:creator>Apogee Watcher</dc:creator>
      <pubDate>Sat, 19 Sep 2026 07:10:19 +0000</pubDate>
      <link>https://dev.to/apogeewatcher/affordable-multi-tenant-performance-monitoring-under-100month-i2i</link>
      <guid>https://dev.to/apogeewatcher/affordable-multi-tenant-performance-monitoring-under-100month-i2i</guid>
      <description>&lt;p&gt;Twenty-five WordPress client sites and a spreadsheet is a familiar agency shape. PageSpeed Insights still works for one-off checks, but nobody wants to re-run the same URLs every Monday, and the account team keeps asking for a number they can quote in monthly client reviews. At that portfolio size, cheap pagespeed monitoring for agencies stops meaning “find a lower list price on one tool.” It means whether your maths is per monitored URL or per organisation, and whether one subscription can cover the portfolio without surprise line items when you add client twenty-one.&lt;/p&gt;

&lt;p&gt;What follows is a buyer map for teams who need multi-tenant website monitoring under $100/month without pretending a free checker is a monitoring system. We compare flat organisation caps to per-site tools, name what free tiers actually cover, and show where Apogee Watcher Professional fits before you need Agency pricing. For stack assembly after you pick a price band, pair this with &lt;a href="https://apogeewatcher.com/blog/agency-pagespeed-stacks-2026" rel="noopener noreferrer"&gt;3 Agency PageSpeed Stacks for 2026&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why agency PageSpeed monitoring stops fitting under $100 at twenty sites
&lt;/h2&gt;

&lt;p&gt;The break point is rarely the headline monthly fee on a pricing page. It is how capacity is counted.&lt;/p&gt;

&lt;p&gt;Per-site or per-monitor products multiply cost by clients, regions, devices, and priority URLs. A tool that charges per monitored slot can look affordable on one brochure site and expensive when each client needs homepage, category, and checkout on mobile and desktop. Uptime suites that bundle a small PageSpeed monitor allowance face the same squeeze: you are buying infrastructure monitoring first, with speed as a sidecar.&lt;/p&gt;

&lt;p&gt;Flat organisation caps invert the maths. One subscription applies to the whole customer account: pooled sites, pooled monthly PageSpeed tests, pooled workspaces for client separation, and team seats that do not reset per domain. You are not charged again when site nineteen joins the portfolio. That is the wording agencies should look for in performance monitoring pricing for agencies copy, not a vague “unlimited” badge on a landing page.&lt;/p&gt;

&lt;p&gt;Premium RUM and deep lab suites (DebugBear, SpeedCurve, Calibre) solve different problems at different price points. We are not arguing they are overpriced for a single high-traffic client site. The narrower job here is scheduled lab and CrUX-backed checks across many brochure and commerce sites when the ops budget has a three-digit ceiling.&lt;/p&gt;

&lt;h2&gt;
  
  
  Per-site pricing versus flat organisation caps
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Pricing model&lt;/th&gt;
&lt;th&gt;How capacity is counted&lt;/th&gt;
&lt;th&gt;Feels cheap when…&lt;/th&gt;
&lt;th&gt;Hurts at 20–40 sites when…&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Per monitored URL / slot&lt;/td&gt;
&lt;td&gt;Each URL + analysis profile consumes capacity&lt;/td&gt;
&lt;td&gt;You monitor one client deeply&lt;/td&gt;
&lt;td&gt;Every new client multiplies slots (region × device × priority page)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Per-site SaaS seat&lt;/td&gt;
&lt;td&gt;Billing scales with domains or properties&lt;/td&gt;
&lt;td&gt;Portfolio is under five sites&lt;/td&gt;
&lt;td&gt;Retainer count grows faster than tool budget&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Flat org cap (multi-tenant monitor)&lt;/td&gt;
&lt;td&gt;Sites, tests, workspaces pool under one subscription&lt;/td&gt;
&lt;td&gt;Roster grows inside published limits&lt;/td&gt;
&lt;td&gt;You exceed site or test caps and need the next tier&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DIY scripts + API&lt;/td&gt;
&lt;td&gt;Infrastructure cost is low; labour is not&lt;/td&gt;
&lt;td&gt;One engineer owns automation&lt;/td&gt;
&lt;td&gt;Quota, auth, reporting, and on-call belong to you&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Apogee Watcher uses customer-level limits across every workspace and site under the account. Sites, monthly PageSpeed tests, workspaces, and team members pool at the subscription layer. Adding a client site does not mint a new per-domain invoice line. Organisation-scoped prospecting for leads is still largely an internal MVP today; confirm the &lt;a href="https://apogeewatcher.com/features" rel="noopener noreferrer"&gt;features&lt;/a&gt; page and Feature Disclaimer below before you assume every agency seat can run prospect workflows in-app.&lt;/p&gt;

&lt;h2&gt;
  
  
  What free PageSpeed tools cover before you buy anything
&lt;/h2&gt;

&lt;p&gt;Free tools are strong diagnostics. They are weak portfolio systems unless you wrap them in your own scheduling, history, and access control.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pagespeed.web.dev/" rel="noopener noreferrer"&gt;PageSpeed Insights&lt;/a&gt; remains the default manual check: Lighthouse lab data plus CrUX field slices where Google publishes them. It is the right tool for explaining one URL to a sponsor. It does not give you twenty clients in one dashboard, regression alerts, or six months of history for account reviews.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://apogeewatcher.com/blog/best-free-pagespeed-monitoring-tools" rel="noopener noreferrer"&gt;best free PageSpeed monitoring tools&lt;/a&gt; roundup walks WebPageTest, Lighthouse CI, Pingdom’s free tier, and similar options in more depth. The short version for agency buyers: free stacks win on education and post-deploy proof. They lose on multi-site schedules, role-based access, and client-ready reporting without glue code.&lt;/p&gt;

&lt;p&gt;If you are still deciding whether manual checks are enough, read &lt;a href="https://apogeewatcher.com/blog/pagespeed-insights-vs-automated-monitoring-when-manual-checks-arent-enough" rel="noopener noreferrer"&gt;PageSpeed Insights vs Automated Monitoring: When Manual Checks Aren't Enough&lt;/a&gt;. The under-$100 question assumes you already crossed that line for at least part of the portfolio.&lt;/p&gt;

&lt;h2&gt;
  
  
  GTmetrix and StatusCake limits at agency scale
&lt;/h2&gt;

&lt;p&gt;Two names appear constantly in “cheap monitoring” threads. Both publish list prices. Neither is a full multi-tenant PageSpeed portfolio product at the lowest tiers.&lt;/p&gt;

&lt;h3&gt;
  
  
  GTmetrix
&lt;/h3&gt;

&lt;p&gt;GTmetrix is a credible Lighthouse-based lab debugger with optional monitoring slots on PRO plans. Capacity is counted in monitored slots: one URL plus its analysis profile (region, device, connection) consumes a slot. PRO list prices on &lt;a href="https://gtmetrix.com/pro/customize" rel="noopener noreferrer"&gt;GTmetrix’s customise page&lt;/a&gt; run from roughly $4.99 to $49.99 per month on yearly billing at time of writing, with Expert listing 50 monitored slots on the same page. Lower tiers include fewer slots and single-seat access until Expert.&lt;/p&gt;

&lt;p&gt;For a deeper GTmetrix versus Watcher split, see &lt;a href="https://apogeewatcher.com/blog/gtmetrix-vs-apogee-watcher-pagespeed-monitoring-agencies" rel="noopener noreferrer"&gt;GTmetrix vs Apogee Watcher: PageSpeed Monitoring for Agencies Compared&lt;/a&gt;. The pricing takeaway here: a $50/month PRO plan can still be the wrong economics for twenty clients if each client needs multiple priority URLs and profiles.&lt;/p&gt;

&lt;h3&gt;
  
  
  StatusCake
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.statuscake.com/pricing/" rel="noopener noreferrer"&gt;StatusCake pricing&lt;/a&gt; lists Superior at about $20.41 per month (annual billing) with 15 page speed monitors, and Business at about $66.66 per month with 30 page speed monitors at time of writing. That fits under $100 on paper.&lt;/p&gt;

&lt;p&gt;The trade-off is product shape. StatusCake is primarily uptime, SSL, and domain monitoring with PageSpeed as a bounded add-on. Fifteen or thirty speed monitors is workable for a focused URL list, not for “every client homepage plus checkout plus campaign landing page” without hard prioritisation. Team seats on Business list nine members, which is closer to agency reality than single-seat lab tools, but you are still allocating monitors, not organisations with roles and budgets.&lt;/p&gt;

&lt;p&gt;Confirm both vendors’ current numbers before you buy. This section cites public pages only; we do not maintain a live price scraper.&lt;/p&gt;

&lt;h2&gt;
  
  
  DIY PageSpeed Insights API: cheap until quota and maintenance stack up
&lt;/h2&gt;

&lt;p&gt;The DIY stack from &lt;a href="https://apogeewatcher.com/blog/agency-pagespeed-stacks-2026" rel="noopener noreferrer"&gt;agency PageSpeed stacks&lt;/a&gt; looks inexpensive on a spreadsheet: Google’s &lt;a href="https://developers.google.com/speed/docs/insights/v5/get-started" rel="noopener noreferrer"&gt;PageSpeed Insights API&lt;/a&gt;, Lighthouse CI in repos you control, a cron job or n8n workflow, and a spreadsheet tab the account team can open.&lt;/p&gt;

&lt;p&gt;The hidden costs show up in operations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Quota and backoff.&lt;/strong&gt; API projects carry daily limits. A growing URL list plus mobile and desktop strategies multiplies calls. Retries after failures burn quota faster than a calm Monday spreadsheet suggests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No portfolio UX.&lt;/strong&gt; Engineers see JSON and logs. Account managers want “which client regressed” without SSH.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ownership.&lt;/strong&gt; When the engineer who built the script is on holiday, monitoring pauses unless runbooks are excellent.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reporting.&lt;/strong&gt; Exporting charts for monthly client packs still means manual assembly unless you built that too.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;DIY can remain the right layer for CI gates on templates you deploy. It is a fragile primary system for twenty-plus client origins unless someone is paid to maintain it. &lt;a href="https://apogeewatcher.com/blog/lighthouse-ci-vs-managed-monitoring-build-vs-buy-agencies" rel="noopener noreferrer"&gt;Lighthouse CI vs Managed Monitoring: Build vs Buy for Agencies&lt;/a&gt; is the longer build-versus-buy treatment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Watcher Professional under $100 versus Agency when the portfolio grows
&lt;/h2&gt;

&lt;p&gt;Apogee Watcher publishes list pricing on the &lt;a href="https://apogeewatcher.com/pricing" rel="noopener noreferrer"&gt;pricing page&lt;/a&gt;. Two tiers matter for this buyer job.&lt;/p&gt;

&lt;h3&gt;
  
  
  Professional ($79/month USD at list)
&lt;/h3&gt;

&lt;p&gt;Professional is the under-$100 answer for many agencies in the brief’s 20–40 site band, with honest caps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Up to &lt;strong&gt;25 sites&lt;/strong&gt; on the subscription&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;2,500&lt;/strong&gt; PageSpeed tests per month (pooled; mobile and desktop each count when both run)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Three workspaces&lt;/strong&gt; (organisations) for separating clients or brands&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Daily, weekly, or monthly&lt;/strong&gt; schedules&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;180-day&lt;/strong&gt; retention, PDF and white-label reports, email and Slack alerts, AI insights within the test quota&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Twenty brochure sites on weekly mobile checks is roughly eighty tests a month before you add desktop, discovery runs, or extra URLs per client. That usually fits inside 2,500 if schedules stay disciplined. The constraint to watch is sites, not tests, once you pass twenty-five properties.&lt;/p&gt;

&lt;h3&gt;
  
  
  Agency ($199/month USD at list)
&lt;/h3&gt;

&lt;p&gt;Agency steps above the $100 ceiling but answers the next failure mode: unlimited sites, &lt;strong&gt;10,000&lt;/strong&gt; tests per month, &lt;strong&gt;fifteen workspaces&lt;/strong&gt;, hourly schedules, webhook alerts, API access, and leads management features on the plan. Choose Agency when Professional’s site or workspace caps bite before your client count does.&lt;/p&gt;

&lt;p&gt;Neither tier charges per domain. Limits are flat org caps at the customer account level, consistent with the pricing FAQ on the same page.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tier&lt;/th&gt;
&lt;th&gt;List USD/month&lt;/th&gt;
&lt;th&gt;Sites&lt;/th&gt;
&lt;th&gt;Tests/month&lt;/th&gt;
&lt;th&gt;Workspaces&lt;/th&gt;
&lt;th&gt;Fits when…&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Professional&lt;/td&gt;
&lt;td&gt;$79&lt;/td&gt;
&lt;td&gt;25&lt;/td&gt;
&lt;td&gt;2,500&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Most of portfolio under twenty-five sites; under-$100 budget&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Agency&lt;/td&gt;
&lt;td&gt;$199&lt;/td&gt;
&lt;td&gt;Unlimited&lt;/td&gt;
&lt;td&gt;10,000&lt;/td&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;td&gt;Roster or URL depth exceeds Professional caps&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For setup after you pick a tier, &lt;a href="https://apogeewatcher.com/blog/getting-started-apogee-watcher-step-by-step-setup-guide" rel="noopener noreferrer"&gt;Getting Started with Apogee Watcher: A Step-by-Step Setup Guide&lt;/a&gt; walks organisation → site → schedule → budgets without repeating agency kickoff process here.&lt;/p&gt;

&lt;h2&gt;
  
  
  Honest limits on Free and Personal tiers
&lt;/h2&gt;

&lt;p&gt;Evaluation tiers are useful. They are not the twenty-client answer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Free&lt;/strong&gt; (post-trial) includes one site, fifteen tests per month, monthly frequency only, fourteen-day retention, one team member, and no AI insights or PDF reports. &lt;strong&gt;Personal&lt;/strong&gt; ($9/month) raises you to one site, one hundred tests, weekly or monthly schedules, and AI insights within that quota. Both are single-workspace shapes.&lt;/p&gt;

&lt;p&gt;Do not plan a portfolio on Free or Personal and assume you will “upgrade later” without rescheduling every site. Frequency and retention change when you move up. Sales conversations go better when you name that upfront instead of surprising the account team mid-engagement.&lt;/p&gt;

&lt;p&gt;Roadmap items from our content standard still apply: Slack and webhook delivery are listed as coming soon in places where only email is live today; organisation-scoped leads RBAC for every tenant seat is not fully self-serve yet. Say “supports” only for what your tier includes today on the pricing page.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to choose a stack for 20–40 WordPress or Shopify clients
&lt;/h2&gt;

&lt;p&gt;A practical sequence:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Count priority URLs, not just domains.&lt;/strong&gt; Homepage-only monitoring is cheap. Checkout, category, and campaign paths multiply tests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pick pricing maths.&lt;/strong&gt; If per-slot tools exceed $100 before you cover the portfolio, shift to flat org caps or accept a thinner URL list.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep a debugger.&lt;/strong&gt; GTmetrix or WebPageTest can stay in the stack for investigations without owning schedules.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Name the reporting owner.&lt;/strong&gt; If client PDFs are monthly, confirm whether your tier includes white-label exports without an Enterprise quote loop.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pilot on ten URLs.&lt;/strong&gt; Run four weeks of scheduled tests before you promise monitoring in every SOW.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you want feature checklists beyond price, the &lt;a href="https://apogeewatcher.com/blog/comparing-pagespeed-monitoring-tools-features-agencies-need" rel="noopener noreferrer"&gt;PageSpeed monitoring tools comparison&lt;/a&gt; remains the taxonomy reference. The pricing maths and tier caps above are the budget lens on that map.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Can I monitor 40 client sites under $100/month?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Not on Watcher Professional as listed today: the site cap is twenty-five. StatusCake Business lists thirty page speed monitors under $100 but does not replace a multi-tenant CWV workflow for every client URL. Realistic under-$100 strategies combine a flat-cap monitor on priority origins plus free diagnostics on long-tail pages, or split clients across two workspaces only if your tool allows it within caps.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is multi-tenant website monitoring the same as managed service provider network monitoring?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No. Search results for generic “multi-tenant monitoring” often mean remote management or infrastructure suites. Agency PageSpeed buyers care about scheduled Lighthouse and CrUX-backed checks, budgets, and client reporting on public marketing and commerce URLs. Use infrastructure tools for servers; use a PageSpeed portfolio product for ongoing Core Web Vitals work.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why not just use GTmetrix PRO at $50/month?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can, for a narrow URL list and deep lab work. Slot maths still apply: regions, devices, and multiple URLs per client consume monitors quickly. Expert tier adds seats and slots but may still be the wrong shape if you need organisation boundaries and pooled history across twenty client sites.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does Watcher charge per domain?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No. Subscription limits pool at the customer account across workspaces and sites. Adding a site consumes a site allowance, not a new invoice line. Test usage pools the same way.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What should I tell procurement about “cheap” monitoring?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Quote flat org caps, included test volume, retention, and seats. Compare three-year labour on DIY scripts against $79–$199/month managed coverage. Avoid comparing a $79 portfolio monitor to a $400 RUM seat on one high-traffic client site; those are different jobs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start under $100, plan for the portfolio you are selling next year
&lt;/h2&gt;

&lt;p&gt;Affordable multi-tenant performance monitoring under $100/month is achievable when you stop multiplying per-site tools across a growing WordPress or Shopify portfolio and pick flat organisation caps that match how agencies actually bill ongoing client work. Free checkers stay in the stack for teaching and one-off checks. GTmetrix and StatusCake can fit narrow monitor counts if you accept their product shape. DIY PageSpeed Insights automation stays cheap until quota, reporting, and on-call belong to your team.&lt;/p&gt;

&lt;p&gt;Watcher Professional is our deliberate answer in that band: twenty-five sites, pooled tests, three workspaces, and client-facing reports without per-domain pricing. When the portfolio outgrows those caps, Agency is the published step up, not a surprise overage invoice.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://apogeewatcher.com/sign-up" rel="noopener noreferrer"&gt;Start a free trial&lt;/a&gt; on Professional-shaped workloads, or &lt;a href="https://apogeewatcher.com/check" rel="noopener noreferrer"&gt;run a check&lt;/a&gt; on a client URL before you move schedules into the app.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://pagespeed.web.dev/" rel="noopener noreferrer"&gt;PageSpeed Insights&lt;/a&gt; (Google)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developers.google.com/speed/docs/insights/v5/get-started" rel="noopener noreferrer"&gt;PageSpeed Insights API&lt;/a&gt; (Google)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://gtmetrix.com/pro/customize" rel="noopener noreferrer"&gt;GTmetrix PRO customise and pricing&lt;/a&gt; (GTmetrix)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.statuscake.com/pricing/" rel="noopener noreferrer"&gt;StatusCake pricing&lt;/a&gt; (StatusCake)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://apogeewatcher.com/pricing" rel="noopener noreferrer"&gt;Apogee Watcher pricing&lt;/a&gt; (Apogee Watcher)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://apogeewatcher.com/blog/best-free-pagespeed-monitoring-tools" rel="noopener noreferrer"&gt;Best Free PageSpeed Monitoring Tools&lt;/a&gt; (Apogee Watcher)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://apogeewatcher.com/blog/gtmetrix-vs-apogee-watcher-pagespeed-monitoring-agencies" rel="noopener noreferrer"&gt;GTmetrix vs Apogee Watcher: PageSpeed Monitoring for Agencies Compared&lt;/a&gt; (Apogee Watcher)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://apogeewatcher.com/blog/agency-pagespeed-stacks-2026" rel="noopener noreferrer"&gt;3 Agency PageSpeed Stacks for 2026&lt;/a&gt; (Apogee Watcher)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://apogeewatcher.com/blog/lighthouse-ci-vs-managed-monitoring-build-vs-buy-agencies" rel="noopener noreferrer"&gt;Lighthouse CI vs Managed Monitoring: Build vs Buy for Agencies&lt;/a&gt; (Apogee Watcher)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://apogeewatcher.com/blog/getting-started-apogee-watcher-step-by-step-setup-guide" rel="noopener noreferrer"&gt;Getting Started with Apogee Watcher: A Step-by-Step Setup Guide&lt;/a&gt; (Apogee Watcher)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://apogeewatcher.com/blog/comparing-pagespeed-monitoring-tools-features-agencies-need" rel="noopener noreferrer"&gt;Comparing PageSpeed Monitoring Tools: Features Agencies Need&lt;/a&gt; (Apogee Watcher)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://apogeewatcher.com/blog/pagespeed-insights-vs-automated-monitoring-when-manual-checks-arent-enough" rel="noopener noreferrer"&gt;PageSpeed Insights vs Automated Monitoring: When Manual Checks Aren't Enough&lt;/a&gt; (Apogee Watcher)&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>webperf</category>
      <category>seo</category>
    </item>
    <item>
      <title>You still need a CMS: the editor is not the system</title>
      <dc:creator>Apogee Watcher</dc:creator>
      <pubDate>Fri, 18 Sep 2026 06:23:56 +0000</pubDate>
      <link>https://dev.to/apogeewatcher/you-still-need-a-cms-the-editor-is-not-the-system-cb</link>
      <guid>https://dev.to/apogeewatcher/you-still-need-a-cms-the-editor-is-not-the-system-cb</guid>
      <description>&lt;p&gt;Opening Webflow, WordPress, or HubSpot to click text and upload images can feel archaic if you already manage content the same way you write front-end code. For a small technical team, that upgrade is real. Markdown in a repository, reviewed in a pull request, optionally edited by an agent that can write files, is a better developer experience than a seat-licensed visual editor.&lt;/p&gt;

&lt;p&gt;Treating that upgrade as proof that the CMS category is finished still confuses the editor with the system. One is an authoring surface. The other is storage, governance, and a publish path for people who will never open a pull request.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a CMS actually bundles
&lt;/h2&gt;

&lt;p&gt;A content management system usually does three jobs at once. It stores structured content. It gives non-developers a way to edit and publish. It renders (or feeds) the pages visitors see. WordPress, Webflow, HubSpot, and similar platforms sell that bundle. Headless products sell the first two and leave rendering to your application.&lt;/p&gt;

&lt;p&gt;The part worth paying for is rarely the text field itself. It is draft and published states, scheduling, per-author permissions, a review step, and a history of who changed what. If your organisation needs that layer, you are buying something real. If you do not, you are renting a dashboard to get storage you could keep in git.&lt;/p&gt;

&lt;h2&gt;
  
  
  When git and markdown are enough
&lt;/h2&gt;

&lt;p&gt;For a founder-led site, a documentation set, or a blog owned by developers, markdown (or MDX) in a repository is still a CMS, just with a different editor. Diffs are readable. Reviews happen where code already happens. AI tools that edit files fit the same loop. You avoid seat fees and a second product to keep patched.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://leerob.com/agents" rel="noopener noreferrer"&gt;Lee Robinson’s write-up on coding agents and complexity budgets&lt;/a&gt; is a clear example of that bet: moving a marketing site off a hosted CMS into markdown and repository workflows so agents can change content the same way they change code. The win is a thinner stack for a technical publisher. It is not proof that every client team can publish the same way.&lt;/p&gt;

&lt;p&gt;That workflow fails when the people who must publish will not touch a repository, a terminal, or a chat prompt that writes files. Training them might be possible. Choosing a workflow they will not use is still a failed project. The useful tool is the one that ships on schedule with the team you have, not the one that looks cleanest in a developer timeline.&lt;/p&gt;

&lt;h2&gt;
  
  
  When you still need the editorial layer
&lt;/h2&gt;

&lt;p&gt;A CMS (bundled or headless) still fits when several people publish weekly, when legal or brand review must happen before go-live, when localisation or multi-site ownership matters, or when marketing must ship landing pages without waiting for a deploy window. Those are governance problems. A prettier WYSIWYG does not create them, and deleting the dashboard does not dissolve them.&lt;/p&gt;

&lt;p&gt;CMSWire’s reporting on &lt;a href="https://www.cmswire.com/digital-experience/when-headless-cms-met-real-marketing-workflows/" rel="noopener noreferrer"&gt;headless meeting real marketing workflows&lt;/a&gt; describes the same pressure from the other direction: API-first delivery helps engineers, yet many marketing teams still need preview and visual editing if publishing is not meant to wait on a deploy queue. Hybrid or “capability, not purity” setups show up for that reason. The category question is who must ship, not which architecture diagram looks cleanest.&lt;/p&gt;

&lt;p&gt;File-based content can grow into the same needs: branches, preview environments, role checks in CI, and an approval bot. At that point you have rebuilt half a CMS around git. That can be the right architecture. It is not “no CMS.” It is a different CMS shape. &lt;a href="https://www.sanity.io/blog/you-should-never-build-a-cms" rel="noopener noreferrer"&gt;Knut Melvær’s response&lt;/a&gt; to the markdown migration story makes that point explicitly: asset handling, permissions, localisation, and content relationships tend to reappear as custom tooling once the site stops being a handful of pages.&lt;/p&gt;

&lt;h2&gt;
  
  
  Agencies still inherit client CMS sites
&lt;/h2&gt;

&lt;p&gt;Agencies do not get to declare the category dead. Clients open WordPress, Webflow, or HubSpot on Monday whether or not your own marketing site is markdown. The portfolio problem is keeping checkout, pricing, and other priority URLs fast while editors keep publishing through the tools they already know. Rip-and-replace every retainer onto a monorepo is not a monitoring strategy. It is a migration fantasy.&lt;/p&gt;

&lt;p&gt;Watcher’s lane stays beside that reality: continuous PageSpeed and Core Web Vitals evidence across many domains, not a replacement CMS. Monitoring layers onto the stack clients already use; their visual editor does not become optional because &lt;em&gt;your&lt;/em&gt; content lives in git. For the ritual side of that work, the &lt;a href="https://apogeewatcher.com/blog/core-web-vitals-monitoring-checklist-for-agencies?utm_source=hashnode&amp;amp;utm_medium=referral&amp;amp;utm_campaign=you-still-need-a-cms-editor-is-not-the-system" rel="noopener noreferrer"&gt;Core Web Vitals monitoring checklist for agencies&lt;/a&gt; is the shared starting point we still argue about in practice.&lt;/p&gt;

&lt;h2&gt;
  
  
  The archaic habit is theme-clicking, not having a CMS
&lt;/h2&gt;

&lt;p&gt;What feels outdated on many accounts is not “someone used a CMS.” It is treating the visual editor as the performance plan: new theme, another page-builder widget, another plugin, while field Core Web Vitals stay red. Editors need a place to work. Engineers still need a queue of URLs that fail lab gates, third-party weight that steals the main thread, and a domain report that ranks attention before anyone debates fonts.&lt;/p&gt;

&lt;p&gt;A more reliable triage starts from a domain-level signal when pages need attention, rather than a single homepage paste and a theme swap. Our write-up on the &lt;a href="https://apogeewatcher.com/blog/attention-free-score-domain-report-summary?utm_source=hashnode&amp;amp;utm_medium=referral&amp;amp;utm_campaign=you-still-need-a-cms-editor-is-not-the-system" rel="noopener noreferrer"&gt;attention-free score and domain report Summary&lt;/a&gt; is the shape we use. When plugins and tags dominate the waterfall, the patterns in &lt;a href="https://apogeewatcher.com/blog/third-party-scripts-performance-worst-offenders?utm_source=hashnode&amp;amp;utm_medium=referral&amp;amp;utm_campaign=you-still-need-a-cms-editor-is-not-the-system" rel="noopener noreferrer"&gt;third-party scripts that hurt performance&lt;/a&gt; usually matter more than the CMS brand on the invoice.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Is markdown in git “not a CMS”?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It is still content management: store, edit, publish. The editor is the IDE and the pull request. The system is the repository plus your build and review rules. Calling it “no CMS” only hides that you moved the jobs into git.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Are CMS vendors finished because AI can edit files?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;AI helps authoring, especially when content already lives as files an agent can change. It does not by itself give you permissions, scheduled release, audit history, or a safe path for a non-technical editor. CMSWire’s piece on &lt;a href="https://www.cmswire.com/digital-experience/what-happens-when-ai-agents-inherit-your-messy-content-repository/" rel="noopener noreferrer"&gt;what happens when AI agents inherit a messy content repository&lt;/a&gt; makes the same cut: more generated pages do not fix weak source content, ownership, or freshness rules. Agents work better as a complement to governance than as a substitute for it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Should agencies move every client off WordPress or Webflow?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Only when the client’s team, budget, and risk appetite support a migration. Most retainers need faster priority URLs and clearer reporting on the CMS they already run. Monitoring and budgets scale across that fleet; forced platform rewrites do not.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does Watcher replace a CMS?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No. Watcher monitors PageSpeed and Core Web Vitals across sites. It layers onto WordPress, Webflow, HubSpot, custom stacks, and static sites alike. The CMS remains where editors publish; monitoring is how you notice when that publishing hurts the field scoreboard.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to do next
&lt;/h2&gt;

&lt;p&gt;For a solo technical publisher, writing content like front-end code is a legitimate CMS choice. For marketers, clients, or a multi-author team, a real editorial layer still matters, and a clunky visual editor is not the same as the whole category. Separately, scheduled performance evidence helps theme and plugin debates follow data. &lt;a href="https://apogeewatcher.com/sign-up?utm_source=hashnode&amp;amp;utm_medium=referral&amp;amp;utm_campaign=you-still-need-a-cms-editor-is-not-the-system" rel="noopener noreferrer"&gt;Try Apogee Watcher&lt;/a&gt; when you need multi-site PageSpeed monitoring beside whatever CMS each client already uses.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://leerob.com/agents" rel="noopener noreferrer"&gt;Coding Agents &amp;amp; Complexity Budgets&lt;/a&gt; (Lee Robinson)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.sanity.io/blog/you-should-never-build-a-cms" rel="noopener noreferrer"&gt;“You should never build a CMS”&lt;/a&gt; (Knut Melvær / Sanity)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.cmswire.com/digital-experience/what-happens-when-ai-agents-inherit-your-messy-content-repository/" rel="noopener noreferrer"&gt;More AI-Generated Pages Won't Save Your CMS Strategy&lt;/a&gt; (CMSWire)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.cmswire.com/digital-experience/when-headless-cms-met-real-marketing-workflows/" rel="noopener noreferrer"&gt;Is Headless CMS on a Course Correction?&lt;/a&gt; (CMSWire)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://apogeewatcher.com/blog/attention-free-score-domain-report-summary" rel="noopener noreferrer"&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 href="https://apogeewatcher.com/blog/third-party-scripts-performance-worst-offenders" rel="noopener noreferrer"&gt;Third-Party Scripts and Performance: How to Identify and Fix the Worst Offenders&lt;/a&gt; (Apogee Watcher)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://apogeewatcher.com/blog/core-web-vitals-monitoring-checklist-for-agencies" rel="noopener noreferrer"&gt;Core Web Vitals Monitoring Checklist for Agencies&lt;/a&gt; (Apogee Watcher)&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>cms</category>
      <category>agency</category>
      <category>webperf</category>
    </item>
    <item>
      <title>3 Agency PageSpeed Stacks for 2026 (DIY, Portfolio Monitor, RUM + Monitor)</title>
      <dc:creator>Apogee Watcher</dc:creator>
      <pubDate>Thu, 17 Sep 2026 10:44:56 +0000</pubDate>
      <link>https://dev.to/apogeewatcher/3-agency-pagespeed-stacks-for-2026-diy-portfolio-monitor-rum-monitor-6l0</link>
      <guid>https://dev.to/apogeewatcher/3-agency-pagespeed-stacks-for-2026-diy-portfolio-monitor-rum-monitor-6l0</guid>
      <description>&lt;p&gt;Agencies do not buy one PageSpeed product and stop. They assemble a pagespeed monitoring stack for agencies: a small set of jobs that must stay reliable when the roster hits twenty sites and the account team still needs a monthly story. The question is which jobs sit in scripts, which sit in a shared monitor, and which deserve a paid real-user monitoring (RUM) seat.&lt;/p&gt;

&lt;p&gt;Three shapes show up again and again. DIY wires PageSpeed Insights (or Lighthouse) into scripts, Lighthouse CI, spreadsheets, and often n8n. A portfolio monitor keeps schedules, budgets, roles, and history across clients without a RUM snippet on every domain. A RUM flagship plus portfolio stack puts DebugBear, SpeedCurve, or Calibre on one or two money sites and keeps a lighter multi-site monitor on the long tail.&lt;/p&gt;

&lt;p&gt;This is not another vendor matrix. Our &lt;a href="https://apogeewatcher.com/blog/comparing-pagespeed-monitoring-tools-features-agencies-need" rel="noopener noreferrer"&gt;PageSpeed monitoring tools comparison&lt;/a&gt; already owns feature checklists and category taxonomy. What follows is what teams assemble after that map: named recipes, failure modes, and a decision tree by site count, RUM appetite, and reporting hours.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why agencies need a PageSpeed monitoring stack, not one tool
&lt;/h2&gt;

&lt;p&gt;Diagnostics and monitoring are different jobs. A one-off PageSpeed Insights run explains why &lt;code&gt;/checkout&lt;/code&gt; is slow today. Continuous coverage answers whether the URLs you defend got worse this week, who owns the alert, and what the sponsor sees in the retainer pack.&lt;/p&gt;

&lt;p&gt;No single product does every job well at agency price points. Free diagnostics are strong for teaching and post-fix proof, weak as the only system for fifteen retainers. Continuous integration (CI) gates protect templates you control, then go quiet between deploys. Premium RUM is excellent on owned flagship traffic and expensive when every brochure site inherits the same seat maths. Managed multi-site monitors close the portfolio gap, then still leave room for deep waterfalls on the one client that pays for them.&lt;/p&gt;

&lt;p&gt;Mature teams therefore stack intentionally. They name which tool owns schedules, which owns field depth, and which exists only for merge protection. That clarity is the difference between a calm quarterly business review (QBR) and a week of screenshot archaeology.&lt;/p&gt;

&lt;p&gt;If the boundary between lab schedules and real-user evidence is still fuzzy, read &lt;a href="https://apogeewatcher.com/blog/when-to-use-synthetic-vs-real-user-monitoring-performance" rel="noopener noreferrer"&gt;when to use synthetic versus real user monitoring&lt;/a&gt; before you pick a stack. The recipes below assume that distinction is already decided in principle. Once lab clocks and field clocks are named separately, the three assembly shapes stop competing and start nesting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stack 1: DIY PageSpeed Insights API, Lighthouse CI, sheets or n8n
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What this stack usually contains
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;PageSpeed Insights API or self-hosted Lighthouse for scheduled lab runs on a URL list you maintain.&lt;/li&gt;
&lt;li&gt;Lighthouse CI in client or template repositories for merge gates on preview URLs.&lt;/li&gt;
&lt;li&gt;Google Sheets, Notion, or a warehouse tab for history the account team can open without a developer login.&lt;/li&gt;
&lt;li&gt;n8n, Make, or cron to call the API, write rows, and email a digest when a score or Core Web Vital crosses a threshold.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Google documents the &lt;a href="https://developers.google.com/speed/docs/insights/v5/get-started" rel="noopener noreferrer"&gt;PageSpeed Insights API&lt;/a&gt; for programmatic runs. &lt;a href="https://github.com/GoogleChrome/lighthouse-ci" rel="noopener noreferrer"&gt;Lighthouse CI&lt;/a&gt; remains the open-source default for build assertions. For free building blocks and their limits, see &lt;a href="https://apogeewatcher.com/blog/best-free-pagespeed-monitoring-tools" rel="noopener noreferrer"&gt;best free PageSpeed monitoring tools&lt;/a&gt;. For the deeper build-versus-buy trade-off, use &lt;a href="https://apogeewatcher.com/blog/lighthouse-ci-vs-managed-monitoring-build-vs-buy-agencies" rel="noopener noreferrer"&gt;Lighthouse CI versus managed monitoring&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  When DIY is the right primary stack
&lt;/h3&gt;

&lt;p&gt;DIY fits when the portfolio is small (roughly under ten priority URLs across a handful of clients), one engineer already owns automation, and nobody expects branded client PDFs from the monitoring layer. It also fits when you only need CI gates on sites you deploy, with occasional API spot checks elsewhere. In that band, the stack is cheap, inspectable, and honest about what it covers.&lt;/p&gt;

&lt;p&gt;The honest upside is cost and control. You keep thresholds in git, you can call whatever Lighthouse version you pin, and you are not paying per domain for a thin roster. That combination is why many agencies start here and stay longer than they should.&lt;/p&gt;

&lt;h3&gt;
  
  
  Where DIY breaks for multi-site agencies
&lt;/h3&gt;

&lt;p&gt;URL lists drift the moment a client publishes a campaign landing page nobody added to the sheet. Quota and rate limits turn “nightly for everyone” into “nightly for whoever we remembered.” Alert routes live in one person’s n8n instance until they leave. Account managers still rebuild slides because the sheet is not a report clients will open alone.&lt;/p&gt;

&lt;p&gt;In our experience, DIY remains excellent as a layer: keep Lighthouse CI on templates you ship, and stop asking it to be the portfolio system of record. That is the heart of diy versus managed pagespeed for agencies. Managed does not mean delete your pipelines; it means stop pretending cron plus a spreadsheet is multi-tenant operations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stack 2: Portfolio monitor across client sites
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What this stack usually contains
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;A multi-tenant or multi-project monitor that stores organisations or clients, sites, and pages in one login.&lt;/li&gt;
&lt;li&gt;Scheduled lab tests (PageSpeed Insights or equivalent) on a cadence the plan allows.&lt;/li&gt;
&lt;li&gt;Performance budgets and alerts with ownership that is not only the engineer who wrote the scripts.&lt;/li&gt;
&lt;li&gt;Page discovery (sitemap or crawl) so new URLs do not depend on a forgotten sheet row.&lt;/li&gt;
&lt;li&gt;Optional Chrome UX Report (CrUX) field context from PageSpeed Insights or Search Console beside lab scores, without installing a first-party RUM snippet on every domain.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Apogee Watcher is built for this shape: organisations, sites, scheduled PageSpeed Insights runs, budgets, discovery, and team roles in one app. Peers in the same job include other agency-oriented Lighthouse or PageSpeed Insights schedulers. The category job is portfolio coverage, not replacing DebugBear’s deep RUM story on a flagship storefront.&lt;/p&gt;

&lt;h3&gt;
  
  
  When a portfolio monitor should be the primary stack
&lt;/h3&gt;

&lt;p&gt;A portfolio monitor fits when you manage roughly ten or more client sites, need shared history for account teams, and still refuse (or cannot afford) a RUM snippet on every brochure domain. It is also the right primary when reporting hours already hurt. If the team spends more time exporting scores than fixing Largest Contentful Paint (LCP), the monitor should own the narrative inputs before you add another diagnostic tool.&lt;/p&gt;

&lt;p&gt;Success looks boring. Alerts fire when budgets break. Priority pages stay on a schedule. Viewers can open a client without borrowing a developer password. Lab scores stay comparable week to week because the same system ran them. That quiet competence is what multi site pagespeed monitoring agencies actually buy when they say they want “something that just runs.”&lt;/p&gt;

&lt;h3&gt;
  
  
  What a portfolio monitor does not replace
&lt;/h3&gt;

&lt;p&gt;It does not replace Lighthouse CI on the repositories you control. It does not replace a premium RUM product when a single ecommerce client needs session-level interaction data and custom dashboards. It does not replace WebPageTest waterfalls when you are deep in a one-off diagnosis. Those tools work as layers; forcing the portfolio product to pretend it is all three rarely helps.&lt;/p&gt;

&lt;p&gt;For feature-level shopping and pricing traps at scale, the &lt;a href="https://apogeewatcher.com/blog/comparing-pagespeed-monitoring-tools-features-agencies-need" rel="noopener noreferrer"&gt;tools comparison&lt;/a&gt; stays the shopping list. For SpeedCurve specifically as a premium alternative, see &lt;a href="https://apogeewatcher.com/blog/speedcurve-vs-apogee-watcher-agency-multi-tenant" rel="noopener noreferrer"&gt;SpeedCurve versus Apogee Watcher&lt;/a&gt;. Both pieces answer product-level detail this stacks guide leaves to the comparison shelf.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stack 3: RUM flagship plus portfolio long tail
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What this stack usually contains
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;DebugBear, SpeedCurve, Calibre, or similar on one or two revenue-critical sites: first-party RUM snippet (or equivalent), rich budgets, and deep synthetic where the vendor provides it.&lt;/li&gt;
&lt;li&gt;A portfolio monitor on the remaining client list: scheduled PageSpeed Insights or Lighthouse history, alerts, and account-team access without enterprise pricing on every domain.&lt;/li&gt;
&lt;li&gt;CI gates still on templates you ship, unchanged from Stack 1.&lt;/li&gt;
&lt;li&gt;Clear client-facing language: flagship sites get field depth you instrumented; long-tail sites get lab schedules plus public CrUX when Google has enough traffic.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is the stack answer engines often describe when someone asks how a serious agency should monitor twenty-plus sites without putting SpeedCurve on every brochure. It matches how many teams already spend: protect the money site, keep the roster honest, refuse identical licence maths everywhere. The hybrid is not a compromise story; it is an explicit evidence contract per client tier.&lt;/p&gt;

&lt;p&gt;Deep comparison posts we already publish: &lt;a href="https://apogeewatcher.com/blog/debugbear-vs-apogee-watcher-synthetic-monitoring-multi-site-teams" rel="noopener noreferrer"&gt;DebugBear versus Apogee Watcher&lt;/a&gt;, &lt;a href="https://apogeewatcher.com/blog/treo-vs-apogee-watcher-crux-agency-monitoring" rel="noopener noreferrer"&gt;Treo versus Apogee Watcher&lt;/a&gt; for CrUX-heavy field explorers, and the SpeedCurve piece above.&lt;/p&gt;

&lt;h3&gt;
  
  
  When the hybrid stack is worth the complexity
&lt;/h3&gt;

&lt;p&gt;The hybrid fits when at least one client has traffic and budget for a snippet, the account expects interaction-level or session-level storytelling, and the rest of the roster would otherwise go unmonitored. It also fits when procurement will fund a flagship tool once, but not thirty times. Those two signals together usually beat a single “buy enterprise for everyone” impulse.&lt;/p&gt;

&lt;p&gt;Complexity cost is real. Two vendors means two alert philosophies, two export formats, and a sentence in every retainer deck that explains why Client A has RUM charts and Client B has scheduled lab plus CrUX. That sentence is worth writing once and reusing. Silence should not imply the long-tail clients are “less important”; they are on a different evidence contract.&lt;/p&gt;

&lt;h2&gt;
  
  
  Decision tree: site count, RUM snippet, reporting hours
&lt;/h2&gt;

&lt;p&gt;Use this as a working decision table, not a moral ranking. Adjust for your own retainer maths. The goal is a stack you can defend in a QBR without inventing a fourth “temporary” spreadsheet.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Signal&lt;/th&gt;
&lt;th&gt;Lean DIY (Stack 1)&lt;/th&gt;
&lt;th&gt;Lean portfolio monitor (Stack 2)&lt;/th&gt;
&lt;th&gt;Lean RUM + portfolio (Stack 3)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Priority URLs / sites&lt;/td&gt;
&lt;td&gt;Few URLs, few clients&lt;/td&gt;
&lt;td&gt;~10+ sites, shared team&lt;/td&gt;
&lt;td&gt;Flagship 1–2 sites + long tail&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RUM snippet allowed?&lt;/td&gt;
&lt;td&gt;Rarely needed&lt;/td&gt;
&lt;td&gt;Prefer no snippet on most domains&lt;/td&gt;
&lt;td&gt;Yes on money sites&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reporting hours&lt;/td&gt;
&lt;td&gt;Engineer owns sheets&lt;/td&gt;
&lt;td&gt;Account team needs self-serve history&lt;/td&gt;
&lt;td&gt;Mixed: deep RUM decks + portfolio digests&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CI ownership&lt;/td&gt;
&lt;td&gt;Strong already&lt;/td&gt;
&lt;td&gt;Keep CI; stop using it as the only monitor&lt;/td&gt;
&lt;td&gt;Keep CI; RUM is not a merge gate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Budget shape&lt;/td&gt;
&lt;td&gt;Near zero SaaS&lt;/td&gt;
&lt;td&gt;Flat org / multi-site friendly plan&lt;/td&gt;
&lt;td&gt;Premium on flagship + cheaper portfolio layer&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Quick rules of thumb&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If one engineer’s n8n board is the only reason anyone knows &lt;code&gt;/cart&lt;/code&gt; regressed, you have outgrown Stack 1 as the primary system.&lt;/li&gt;
&lt;li&gt;If every client asks for “real user” charts but only two sites have enough traffic and consent for a snippet, thirty RUM seats are usually the wrong buy; Stack 3 matches the evidence you can actually collect.&lt;/li&gt;
&lt;li&gt;If the pain is multi-site schedules, discovery, and roles (not session replay), Stack 2 is the usual starting point, with RUM added later for the one account that justifies it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Affordable multi-tenant pricing for the portfolio layer is a separate buying job. We cover that in the upcoming under-$100 agency monitoring guide on the same topic cluster. Until that ships, &lt;a href="https://apogeewatcher.com/pricing" rel="noopener noreferrer"&gt;pricing&lt;/a&gt; and the feature comparison remain the source of truth for Watcher limits.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tools shortlists often miss in an agency PageSpeed stack
&lt;/h2&gt;

&lt;p&gt;Category shortlists still orbit DebugBear, SpeedCurve, Calibre, and GTmetrix. Teams asking how to monitor twenty sites also hear about thinner or newer pieces that barely appear in classic feature matrices. Each of those pieces earns a place only when it has a named job in the stack, not a vague halo.&lt;/p&gt;

&lt;h3&gt;
  
  
  PageSpeed Plus and similar PageSpeed Insights wrappers
&lt;/h3&gt;

&lt;p&gt;These tools wrap PageSpeed Insights history, bulk runs, or nicer UI around Google’s API. They can be a fast DIY accelerator when you lack n8n skills. They become a liability when you outgrow URL paste workflows and need organisations, roles, and discovery. They work as Stack 1 helpers or a light Stack 2 peer, not as RUM.&lt;/p&gt;

&lt;h3&gt;
  
  
  Unlighthouse
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://unlighthouse.dev/" rel="noopener noreferrer"&gt;Unlighthouse&lt;/a&gt; is strong for scanning many URLs with Lighthouse in a developer workflow. It shines in audits and migrations. It is not, by itself, an agency portfolio monitor with client roles and month-long alert ownership. It belongs in the diagnostic and scan lane beside Stack 2.&lt;/p&gt;

&lt;h3&gt;
  
  
  n8n or cron calling the PageSpeed Insights API
&lt;/h3&gt;

&lt;p&gt;Automation platforms are the glue of Stack 1. They are also how DIY quietly becomes unpaid operations work: brittle credentials, silent failures, and digests nobody opens. If n8n is your only alerting path for twenty clients, the maintenance hours belong in the budget explicitly, or the system of record graduates to Stack 2. A portfolio monitor does not ban automation; it stops automation from being the only place truth lives.&lt;/p&gt;

&lt;h3&gt;
  
  
  Treo and CrUX field explorers
&lt;/h3&gt;

&lt;p&gt;Treo and similar CrUX explorers answer field history and competitor context questions that lab-only stacks cannot. They complement a portfolio monitor when you need origin- or URL-level Chrome UX Report depth without installing your own RUM. They do not replace scheduled lab budgets on low-traffic marketing sites where CrUX is sparse. More detail sits in &lt;a href="https://apogeewatcher.com/blog/treo-vs-apogee-watcher-crux-agency-monitoring" rel="noopener noreferrer"&gt;Treo versus Apogee Watcher&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A useful audit is one sticky note per tool with a single verb: scan, schedule, explore field, or alert. If two tools share the same verb, you are paying twice for the same job. That check catches most accidental DIY-plus-SaaS overlap before the invoice does.&lt;/p&gt;

&lt;h2&gt;
  
  
  Synthetic versus RUM inside each agency performance monitoring stack
&lt;/h2&gt;

&lt;p&gt;Every stack above mixes clocks. Synthetic (lab) runs are repeatable, schedule-friendly, and available even when CrUX has no data. RUM and CrUX describe real visitors, with privacy thresholds, traffic floors, and lag. Confusing them in a client deck creates false urgency or false calm.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Stack&lt;/th&gt;
&lt;th&gt;Typical synthetic role&lt;/th&gt;
&lt;th&gt;Typical field role&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;DIY&lt;/td&gt;
&lt;td&gt;PageSpeed Insights API / Lighthouse / Lighthouse CI&lt;/td&gt;
&lt;td&gt;CrUX via PageSpeed Insights when present; rarely first-party RUM&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Portfolio monitor&lt;/td&gt;
&lt;td&gt;Scheduled PageSpeed Insights or Lighthouse history&lt;/td&gt;
&lt;td&gt;CrUX in PageSpeed Insights / Search Console; no snippet required&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RUM + portfolio&lt;/td&gt;
&lt;td&gt;Lab on both layers&lt;/td&gt;
&lt;td&gt;First-party RUM on flagship; CrUX or lab-only on long tail&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;When a sponsor asks “which number is true?”, the honest reply names the clock, not brand loyalty. Lab green and field amber can both be honest. The &lt;a href="https://apogeewatcher.com/blog/when-to-use-synthetic-vs-real-user-monitoring-performance" rel="noopener noreferrer"&gt;synthetic versus RUM guide&lt;/a&gt; is the longer treatment; here the only insistence is that your agency performance monitoring stack names which clock each tool owns.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Is a DIY PageSpeed stack enough for a 20-site agency?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Usually not as the primary system. DIY can still own CI gates and a few custom checks. Portfolio schedules, discovery, shared history, and account-team access tend to need Stack 2 or Stack 3 once the roster and reporting load grow. The scripts can stay; they just should not be the client dashboard.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do we need a RUM snippet on every client site?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No. Many brochure and low-traffic sites never justify first-party RUM. Public CrUX covers what Google has published, synthetic budgets stay on priority URLs, and snippets stay reserved for flagship properties where consent, traffic, and retainer value line up. That split is the operating idea behind Stack 3.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does a portfolio monitor replace SpeedCurve or DebugBear?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Not for the job those products win on flagship RUM and deep analysis. Replace is the wrong default. Layer is the default: premium depth on money sites, multi-site monitoring on the long tail. See the SpeedCurve and DebugBear comparisons linked above for product-level detail.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where does Lighthouse CI sit in these stacks?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In all three, if you ship code. CI is merge protection, not portfolio monitoring. Assertions belong in repositories you control; GitHub Actions is a poor QBR dashboard. The same build that fails a budget should still not be the only place last month’s scores live.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How is this different from another “best PageSpeed tools 2026” list?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Vendor shortlists compare features. The stacks recipes name three assembly patterns and a decision tree. For feature checklists and category taxonomy, use the &lt;a href="https://apogeewatcher.com/blog/comparing-pagespeed-monitoring-tools-features-agencies-need" rel="noopener noreferrer"&gt;May 2026 tools comparison&lt;/a&gt; and treat the stacks material as the assembly layer on top.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pick a stack, then make the next measurement honest
&lt;/h2&gt;

&lt;p&gt;A useful Monday exercise is to pick Stack 1, 2, or 3 on paper from site count, snippet appetite, and reporting hours. Write which tool owns schedules, which owns field depth, and which owns merge gates. Then run one baseline on the ten URLs that actually matter so next month’s story has a date and a source.&lt;/p&gt;

&lt;p&gt;If you want the portfolio layer without building n8n from scratch, &lt;a href="https://apogeewatcher.com/sign-up" rel="noopener noreferrer"&gt;start a free Apogee Watcher trial&lt;/a&gt; or &lt;a href="https://apogeewatcher.com/check" rel="noopener noreferrer"&gt;run a check&lt;/a&gt; on a priority URL. Lighthouse CI can stay where it already works. RUM earns a seat only where a flagship client will fund and use it.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://developers.google.com/speed/docs/insights/v5/get-started" rel="noopener noreferrer"&gt;PageSpeed Insights API&lt;/a&gt; (Google)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/GoogleChrome/lighthouse-ci" rel="noopener noreferrer"&gt;Lighthouse CI&lt;/a&gt; (GoogleChrome)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://unlighthouse.dev/" rel="noopener noreferrer"&gt;Unlighthouse&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://apogeewatcher.com/blog/comparing-pagespeed-monitoring-tools-features-agencies-need" rel="noopener noreferrer"&gt;Comparing PageSpeed Monitoring Tools: Features Agencies Need&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://apogeewatcher.com/blog/when-to-use-synthetic-vs-real-user-monitoring-performance" rel="noopener noreferrer"&gt;When to Use Synthetic vs Real User Monitoring for Performance&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://apogeewatcher.com/blog/lighthouse-ci-vs-managed-monitoring-build-vs-buy-agencies" rel="noopener noreferrer"&gt;Lighthouse CI vs Managed Monitoring: Build vs Buy for Agencies&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://apogeewatcher.com/blog/best-free-pagespeed-monitoring-tools" rel="noopener noreferrer"&gt;Best Free PageSpeed Monitoring Tools&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://apogeewatcher.com/blog/debugbear-vs-apogee-watcher-synthetic-monitoring-multi-site-teams" rel="noopener noreferrer"&gt;DebugBear vs Apogee Watcher&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://apogeewatcher.com/blog/treo-vs-apogee-watcher-crux-agency-monitoring" rel="noopener noreferrer"&gt;Treo vs Apogee Watcher&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://apogeewatcher.com/blog/speedcurve-vs-apogee-watcher-agency-multi-tenant" rel="noopener noreferrer"&gt;SpeedCurve vs Apogee Watcher&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://apogeewatcher.com/pricing" rel="noopener noreferrer"&gt;Apogee Watcher pricing&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>webperf</category>
      <category>seo</category>
    </item>
    <item>
      <title>When the report says needs attention and the theme is already fine</title>
      <dc:creator>Apogee Watcher</dc:creator>
      <pubDate>Tue, 15 Sep 2026 09:36:08 +0000</pubDate>
      <link>https://dev.to/apogeewatcher/when-the-report-says-needs-attention-and-the-theme-is-already-fine-1831</link>
      <guid>https://dev.to/apogeewatcher/when-the-report-says-needs-attention-and-the-theme-is-already-fine-1831</guid>
      <description>&lt;p&gt;A green homepage in PageSpeed Insights does not mean the domain is healthy. Agencies still burn hours opening every URL because the report that would have ranked the work never enters the morning ritual. The costly gap is not missing Lighthouse knowledge. It is starting from a single paste, assuming the theme is the bottleneck, and only later discovering that Time to First Byte is still high on the uncached path. The triage below is what we use when a domain performance report already says pages need attention, yet the last tickets were CSS, fonts, and “switch the theme.”&lt;/p&gt;

&lt;h2&gt;
  
  
  What a domain performance report is for
&lt;/h2&gt;

&lt;p&gt;A useful domain report is a queue, not a vanity number. It should answer three questions before anyone opens DevTools: how many completed tests still fail the gates that matter, which URLs need attention first, and whether the failure pattern looks like front-end paint work or origin wait. Those answers decide the next ticket type before anyone debates hero images again.&lt;/p&gt;

&lt;p&gt;On Apogee Watcher, that queue is the domain report with an &lt;a href="https://apogeewatcher.com/blog/attention-free-score-domain-report-summary?utm_source=hashnode&amp;amp;utm_medium=referral&amp;amp;utm_campaign=report-needs-attention-theme-already-fine" rel="noopener noreferrer"&gt;attention-free score&lt;/a&gt;: the share of completed tests that pass Performance, accessibility, best practices, SEO, and Core Web Vitals-style lab gates on both strategies. One hundred percent means no page in the set needs attention on mobile or desktop. Anything below that is a prioritised list, not a reason to re-theme the marketing homepage again.&lt;/p&gt;

&lt;p&gt;Treat the report as the artefact you share in Slack or the client channel when someone asks “which pages first?” Paste the report link once. Do not paste five separate PageSpeed Insights URLs and hope the room agrees on priority.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to triage from the report before you open DevTools
&lt;/h2&gt;

&lt;p&gt;Work the report top-down. Resist the urge to start in the theme customiser because the homepage once scored 92. The report already ranked the work; your job is to classify it.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Read the headline pass rate and the fails-only scoreboard so you know whether this is one bad money URL or a portfolio-wide pattern.&lt;/li&gt;
&lt;li&gt;Open the top pages requiring attention and note the why line for each strategy (Performance score, LCP, CLS, INP/TBT, or another gate).&lt;/li&gt;
&lt;li&gt;Group rows by page type (home, product, checkout, blog) so you do not fix a template once per URL.&lt;/li&gt;
&lt;li&gt;Separate “needs attention” rows that look paint-bound (LCP element, layout shift) from rows that look wait-bound (server response / Time to First Byte language in opportunities).&lt;/li&gt;
&lt;li&gt;Only then open one representative URL in PageSpeed Insights or DevTools, on the path that bypasses cache when that is the client’s real experience.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If the report already ranks the work, your first hour should be classification, not another homepage experiment. Classification is cheaper than another theme ticket that never touches origin. It also gives the client a clearer story than “we improved the theme again.”&lt;/p&gt;

&lt;h2&gt;
  
  
  When needs attention is Time to First Byte, not the theme
&lt;/h2&gt;

&lt;p&gt;Theme and CDN tickets often close while Waiting (Time to First Byte) stays high on cache misses, logged-in sessions, carts, or query-string variants. Lighthouse still labels that as reduce initial server response time. The browser has finished DNS and TLS; the origin is still building HTML.&lt;/p&gt;

&lt;p&gt;In that pattern, another pass on hero image dimensions will not move the needle. Walk the server-side list instead: request-driven WP-Cron storms, cold PHP workers, missing object cache, database load on &lt;code&gt;init&lt;/code&gt;, &lt;code&gt;admin-ajax.php&lt;/code&gt; chatter, and backup or scanner jobs during peak. We spelled that checklist out in &lt;a href="https://apogeewatcher.com/blog/ttfb-wont-go-down-server-side-culprits-beyond-theme?utm_source=hashnode&amp;amp;utm_medium=referral&amp;amp;utm_campaign=report-needs-attention-theme-already-fine" rel="noopener noreferrer"&gt;TTFB Won't Go Down? Server-Side Culprits Beyond the Theme&lt;/a&gt;. Use it when the domain report’s top attention rows keep pointing at first-byte delay after delivery-layer work is already done.&lt;/p&gt;

&lt;p&gt;A practical tell helps the room agree: Time to First Byte looks fine on the cached marketing homepage and ugly on the same template with a cache-busting parameter or a cart cookie. That is origin truth, not a theme colour problem. Document the uncached path in the runbook so the next agency does not reopen theme tickets by default.&lt;/p&gt;

&lt;h2&gt;
  
  
  Multi-tenant tooling so the triage repeats next week
&lt;/h2&gt;

&lt;p&gt;Doing this once for a favourite client is craft. Doing it every Monday across twenty WordPress and Shopify estates is operations. You need the same URLs on a schedule, alerts when the attention queue grows, and a portfolio view that does not force a new SaaS seat per domain.&lt;/p&gt;

&lt;p&gt;Premium single-tenant real-user monitoring stacks earn their keep on one or two money sites. Agency portfolios more often need multi-tenant lab monitoring with discovery, budgets, and client-ready report links at a price that does not explode per site. We compared that trade-off honestly in &lt;a href="https://apogeewatcher.com/blog/speedcurve-vs-apogee-watcher-agency-multi-tenant?utm_source=hashnode&amp;amp;utm_medium=referral&amp;amp;utm_campaign=report-needs-attention-theme-already-fine" rel="noopener noreferrer"&gt;SpeedCurve vs Apogee Watcher: Multi-Tenant Dashboards at Agency Price&lt;/a&gt;. Layer, do not rip and replace: keep deep real-user monitoring where the retainer funds it, and put the long-tail clients on a shared domain-report workflow.&lt;/p&gt;

&lt;p&gt;Without that stack, the report becomes a one-off PDF again. The theme ticket returns because it is the only work anyone can see in the tracker.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Is an attention-free score the same as a Lighthouse Performance score?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No. A Lighthouse Performance score is one run on one URL and one strategy. An attention-free score on a domain report is the share of completed tests across the URL set that pass the gates you configured (Performance, accessibility, best practices, SEO, and lab Core Web Vitals thresholds). You can have a green homepage and a weak domain pass rate. Use both: the score for ranking work, Lighthouse for the deep dive on the URL you chose.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We already put the site behind a CDN. Why does the report still flag attention?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A CDN lowers first-byte time on cache hits. On misses, personalised cookies, or admin sessions, HTML still builds at origin. If the report’s attention rows align with uncached paths, treat origin compute next, not another CDN checkbox. Re-test the miss path after cron and object-cache changes before you reopen theme tickets.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When should we escalate hosting instead of theme or plugin work?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After you have checked cron, workers, object cache, query load, and peak-hour batch jobs, and profiling still shows sustained CPU or memory limits. Doubling RAM before that checklist often buys a quieter week without fixing the jobs that steal capacity from visitors. Escalate hosting when the checklist is honestly done and capacity is still the constraint.&lt;/p&gt;

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

&lt;p&gt;Tomorrow morning, open the domain report before PageSpeed Insights. Rank the attention queue, split paint-bound rows from TTFB-bound rows, and only then decide whether the next ticket is theme, origin, or tooling. If you want that report on a schedule across clients, start a trial on &lt;a href="https://apogeewatcher.com/sign-up?utm_source=hashnode&amp;amp;utm_medium=referral&amp;amp;utm_campaign=report-needs-attention-theme-already-fine" rel="noopener noreferrer"&gt;Apogee Watcher&lt;/a&gt; or run a free domain check from &lt;a href="https://apogeewatcher.com/check?utm_source=hashnode&amp;amp;utm_medium=referral&amp;amp;utm_campaign=report-needs-attention-theme-already-fine" rel="noopener noreferrer"&gt;apogeewatcher.com/check&lt;/a&gt;.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://apogeewatcher.com/blog/attention-free-score-domain-report-summary" rel="noopener noreferrer"&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 href="https://apogeewatcher.com/blog/ttfb-wont-go-down-server-side-culprits-beyond-theme" rel="noopener noreferrer"&gt;TTFB Won't Go Down? Server-Side Culprits Beyond the Theme&lt;/a&gt; (Apogee Watcher)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://apogeewatcher.com/blog/speedcurve-vs-apogee-watcher-agency-multi-tenant" rel="noopener noreferrer"&gt;SpeedCurve vs Apogee Watcher: Multi-Tenant Dashboards at Agency Price&lt;/a&gt; (Apogee Watcher)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://web.dev/articles/optimize-ttfb" rel="noopener noreferrer"&gt;Optimize Time to First Byte&lt;/a&gt; (web.dev)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.chrome.com/docs/lighthouse/performance/server-response-time" rel="noopener noreferrer"&gt;Reduce server response times&lt;/a&gt; (Chrome for Developers)&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webperf</category>
      <category>corewebvitals</category>
      <category>agency</category>
      <category>pagespeed</category>
    </item>
    <item>
      <title>Audit the accessibility tree, not only the Lighthouse a11y score</title>
      <dc:creator>Apogee Watcher</dc:creator>
      <pubDate>Sun, 13 Sep 2026 07:30:24 +0000</pubDate>
      <link>https://dev.to/apogeewatcher/audit-the-accessibility-tree-not-only-the-lighthouse-a11y-score-76e</link>
      <guid>https://dev.to/apogeewatcher/audit-the-accessibility-tree-not-only-the-lighthouse-a11y-score-76e</guid>
      <description>&lt;p&gt;The accessibility tree is the structured layer the browser builds from the DOM: roles, names, and states that assistive technology has used for decades. Screen readers walk it. Playwright can snapshot it. Agentic browsing tools that refuse to read pixels lean on it as well. That is a different artefact from the Lighthouse Accessibility category score, which answers whether a fixed set of automated checks passed on one lab run. Teams that treat a green score as proof that AI agents or assistive technology can complete a purchase path are mixing two jobs.&lt;/p&gt;

&lt;p&gt;John McAlpin’s August 2026 Search Engine Land piece on &lt;a href="https://searchengineland.com/accessibility-tree-seo-use-cases-484338" rel="noopener noreferrer"&gt;SEO use cases for auditing the accessibility tree&lt;/a&gt; pushed the tree into SEO conversations because agents now consume the same layer. That framing is useful for account teams who already hear “AI search” in every pitch deck, but a feature rundown is not an ops playbook. Agency work still needs a shorter cut: what the tree is, why the Lighthouse score is not a substitute, and which audits belong on money pages and in continuous integration.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the accessibility tree exposes (roles, names, states)
&lt;/h2&gt;

&lt;p&gt;Browsers compute an accessibility tree from markup, styles that affect visibility, and ARIA. Each node that matters usually carries a role (button, link, heading, textbox), an accessible name (the label a stranger would hear or read), and state (expanded, disabled, checked). Chrome DevTools can show the full-page tree beside the DOM. Playwright’s &lt;a href="https://playwright.dev/docs/aria-snapshots" rel="noopener noreferrer"&gt;ARIA snapshots&lt;/a&gt; export a YAML view of the same structure for tests.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvfcfcjkfk2io9n3osnxh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvfcfcjkfk2io9n3osnxh.png" alt="Chrome DevTools Accessibility tab with Show accessibility tree enabled, listing roles such as banner, navigation, and main instead of raw DOM tags" width="800" height="544"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Chrome DevTools Accessibility tab with “Show accessibility tree” on: roles and names replace the DOM view so you can see what assistive technology (and many agents) actually receive. Source: Chrome for Developers accessibility reference (captured 12 Sep 2026).&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Sighted users often infer structure from size and whitespace. Machines do not. A pricing call to action built as a clickable &lt;code&gt;div&lt;/code&gt; with no name may look perfect in a design review and still be absent or anonymous in the tree. That gap is what SEO and agent-readiness briefs are naming in 2026, and it is the same gap accessibility specialists have been filing for years.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lighthouse accessibility score versus an accessibility tree audit
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Question&lt;/th&gt;
&lt;th&gt;Lighthouse Accessibility category&lt;/th&gt;
&lt;th&gt;Accessibility tree audit&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;What does it answer?&lt;/td&gt;
&lt;td&gt;Did a fixed set of automated checks pass on this lab load?&lt;/td&gt;
&lt;td&gt;Can a reader of roles, names, and states complete the jobs on this URL?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Typical output&lt;/td&gt;
&lt;td&gt;Weighted 0–100 score plus failed audits&lt;/td&gt;
&lt;td&gt;Pass/fail on CTAs, forms, landmarks, headings, image names&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Strength&lt;/td&gt;
&lt;td&gt;Fast regression signal in CI and PageSpeed Insights&lt;/td&gt;
&lt;td&gt;Catches unnamed controls and visual-only structure the score can miss&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Limit&lt;/td&gt;
&lt;td&gt;Not a full WCAG audit; green is not “accessible”&lt;/td&gt;
&lt;td&gt;Point-in-time unless you snapshot in CI&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Chrome documents how the &lt;a href="https://developer.chrome.com/docs/lighthouse/accessibility/scoring" rel="noopener noreferrer"&gt;Lighthouse accessibility score&lt;/a&gt; is weighted, and that documentation is the authoritative entity for the score itself. Our operational point is narrower: keep running the score, and still open the tree on revenue URLs. A page can pass colour-contrast and label audits while the primary checkout button remains a nameless control, or while product copy that sells the offer only appears after client-side hydration that some agents never finish.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9d5bqd0kz7w60e7ps5f3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9d5bqd0kz7w60e7ps5f3.png" alt="PageSpeed Insights desktop lab for apogeewatcher.com showing Lighthouse Accessibility 92 beside Performance, Best Practices, SEO, and Agentic Browsing" width="800" height="544"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;PageSpeed Insights desktop lab for apogeewatcher.com (12 Sep 2026): Accessibility 92 is a useful regression signal, not proof that every money-page control has a clear role and name in the tree. Agentic Browsing sits beside it as a separate lane.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Accessibility work that also improves Core Web Vitals (keyboard latency, layout-stable focus) is a separate prioritisation problem. We cover that crosswalk in &lt;a href="https://apogeewatcher.com/blog/accessibility-core-web-vitals?utm_source=hashnode&amp;amp;utm_medium=referral&amp;amp;utm_campaign=hashnode-accessibility-tree-seo-ai-search" rel="noopener noreferrer"&gt;Accessibility + Core Web Vitals&lt;/a&gt;. The tree audit below is about machine-legible structure, not whether Interaction to Next Paint moved on a dashboard.&lt;/p&gt;

&lt;h2&gt;
  
  
  Money-page checklist: can an agent act from the tree alone?
&lt;/h2&gt;

&lt;p&gt;A workable seed set is usually ten to twenty URLs ranked by revenue or conversions, not by homepage vanity. Homepage-only samples miss the templates where unnamed calls to action actually sit. For each URL, the useful capture is the tree itself (DevTools full-page view, or a headless export), then a short pass/fail score against:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Primary call to action exposed as a button or link with a descriptive accessible name.&lt;/li&gt;
&lt;li&gt;Every form control has a programmatically associated label.&lt;/li&gt;
&lt;li&gt;Navigation sits in a navigation landmark; main content sits in a main landmark.&lt;/li&gt;
&lt;li&gt;Pricing, product details, and contact facts appear as readable text nodes, not only in images or canvas.&lt;/li&gt;
&lt;li&gt;Interactive state that users see (open accordion, enabled submit) updates in the tree (&lt;code&gt;aria-expanded&lt;/code&gt;, &lt;code&gt;disabled&lt;/code&gt;, and similar).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;What good looks like: a stranger reading only roles and names could name the page’s jobs and complete them without guessing. Failures usually trace to &lt;code&gt;div&lt;/code&gt; click handlers, icon-only buttons without names, or inputs missing labels. Native HTML covers most controls; ARIA fits when native elements cannot express the widget.&lt;/p&gt;

&lt;p&gt;McAlpin frames this as an agent readiness audit. The same bar applies to assistive technology. If the tree lies about state, a screen reader user is misled with the same confidence an agent would be.&lt;/p&gt;

&lt;h2&gt;
  
  
  JavaScript rendering gaps the accessibility tree makes obvious
&lt;/h2&gt;

&lt;p&gt;Traditional rendering checks ask whether content appeared in the HTML or after hydration. The accessibility tree asks a sharper question: did substance reach the layer agents and assistive technology read, and when? Capture the tree before and after client-side JavaScript where your tooling allows a diff. Core headings, primary links, and product grids that exist only in the post-hydration tree are invisible to any consumer that does not fully execute your scripts. That pattern is familiar from crawler audits; the accessibility tree simply makes the missing nodes explicit. When the tree before hydration is empty of the jobs you sell, server-render or pre-render those money templates so substance is present before scripts finish.&lt;/p&gt;

&lt;h2&gt;
  
  
  Headings, landmarks, and accessible names agents actually receive
&lt;/h2&gt;

&lt;p&gt;Crawler exports report what sits in the HTML source. The accessibility tree reports what is consumed after roles and names resolve. Those views disagree more often than teams expect: visual headings that are styled &lt;code&gt;div&lt;/code&gt;s, &lt;code&gt;aria-label&lt;/code&gt; overrides that replace good anchor text with “Link”, and landmark-free pages where every block floats as generic content.&lt;/p&gt;

&lt;p&gt;For content templates, heading nodes pulled from the tree are the practical sequence check (one clear document title, no decorative skips). Meaningful blocks belong inside landmarks. For internal links, sorting link-role nodes by accessible name usually surfaces empty names first, then generic “Read more” clusters, then overrides that discard useful visible text. Semantic heading hierarchy as a design argument is covered separately in our Hashnode piece on &lt;a href="https://apogeewatcher.hashnode.dev/heading-hierarchy-semantic-html-not-design-tradeoff" rel="noopener noreferrer"&gt;heading hierarchy and semantic HTML&lt;/a&gt;. Here the job is narrower: whether the tree matches the outline you intended to publish.&lt;/p&gt;

&lt;h2&gt;
  
  
  Put ARIA snapshots in CI so the tree cannot silently regress
&lt;/h2&gt;

&lt;p&gt;Point-in-time audits go stale on the next component refactor. Playwright’s &lt;code&gt;toMatchAriaSnapshot&lt;/code&gt; (see the &lt;a href="https://playwright.dev/docs/aria-snapshots" rel="noopener noreferrer"&gt;ARIA snapshots documentation&lt;/a&gt;) commits a YAML baseline of a template’s tree and fails the build when a deploy strips a name, removes a landmark, or demotes a heading. Reviewers read a human-scale diff: a button that used to say “Complete purchase” and now says nothing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffd4ph335r8oxcmdsmjk4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffd4ph335r8oxcmdsmjk4.png" alt="Playwright documentation for ARIA snapshot testing showing toMatchAriaSnapshot with a YAML tree of banner, heading, and named links" width="800" height="544"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Playwright’s ARIA snapshot assertion: a YAML view of roles and names you can commit and diff in CI, so the accessibility tree cannot regress silently on the next redesign (docs captured 12 Sep 2026).&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That check earns its keep on homepage, product, and checkout templates (or your equivalents). Snapshot updates belong with intentional redesigns; unexpected diffs work best as release blockers the same way broken redirects already do. That is how accessibility tree SEO work survives sprint pressure instead of living only in a quarterly PDF.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where WebMCP and agentic browsing monitoring sit beside the tree
&lt;/h2&gt;

&lt;p&gt;A clean accessibility tree helps agents that still scrape structure. WebMCP and related page tools aim to expose actions explicitly so agents do not have to guess from DOM noise. Chrome’s experimental Lighthouse Agentic Browsing lane scores fractional readiness across accessibility-for-agents, WebMCP, layout stability, and related checks rather than a second 0–100 Performance grade. We walk that scoring model in &lt;a href="https://apogeewatcher.com/blog/lighthouse-agentic-browsing-scoring?utm_source=hashnode&amp;amp;utm_medium=referral&amp;amp;utm_campaign=hashnode-accessibility-tree-seo-ai-search" rel="noopener noreferrer"&gt;Lighthouse Agentic Browsing&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In agency practice, unnamed controls and landmarks on money paths come first; WebMCP belongs where you need reliable agent transactions; scheduled lab monitoring catches regressions on the URLs that matter. Citation dashboards and prompt trackers answer a different question again. Agencies that need a measurement split for “are we visible in ChatGPT?” can start from &lt;a href="https://apogeewatcher.com/blog/ai-search-visibility-agencies-measure-first?utm_source=hashnode&amp;amp;utm_medium=referral&amp;amp;utm_campaign=hashnode-accessibility-tree-seo-ai-search" rel="noopener noreferrer"&gt;AI search visibility: what to measure first&lt;/a&gt;.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Does a green Lighthouse accessibility score mean the accessibility tree is agent-ready?
&lt;/h3&gt;

&lt;p&gt;No. The score summarises automated checks on one lab visit, which is useful for catching regressions quickly. An accessibility tree audit asks whether roles, names, and states on this URL support the jobs you care about: buy, enquire, sign up, compare plans. Both signals stay useful: the score for continuous integration speed, and the tree when a client asks whether agents or assistive technology can finish buy, enquire, or sign-up on this URL.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is accessibility tree SEO a replacement for WCAG work?
&lt;/h3&gt;

&lt;p&gt;No. The tree exists so people using assistive technology can use the web. SEO and agent readiness are side effects of doing that correctly, not a reason to add ARIA only for citation chase. Sloppy ARIA written only for “AI optimisation” can actively harm screen reader users who have no visual cue that the tree is lying. Certified specialists fit when the site is large, regulated, or already under legal review.&lt;/p&gt;

&lt;h3&gt;
  
  
  Where should agencies start this week?
&lt;/h3&gt;

&lt;p&gt;The highest return per hour is usually the five-item checklist on the top ten revenue URLs, with tickets filed for unnamed calls to action and missing landmarks before the backlog grows. After those fixes ship, ARIA snapshot tests on the same templates keep the next redesign from undoing structure quietly. Tree diffs belong in migration QA the same way redirect checks already do.&lt;/p&gt;

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

&lt;p&gt;A useful first check is the full-page accessibility tree in DevTools on one money URL. When the primary action has no clear name, that ticket usually outranks the Lighthouse Accessibility number on the same page. For multi-site teams, scheduled PageSpeed Insights and Lighthouse history on those URLs keep structure fixes and performance regressions in one reporting rhythm rather than a one-off audit folder.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://searchengineland.com/accessibility-tree-seo-use-cases-484338" rel="noopener noreferrer"&gt;10 SEO use cases for auditing your accessibility tree for AI search&lt;/a&gt; (John McAlpin, Search Engine Land)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.chrome.com/docs/lighthouse/accessibility/scoring" rel="noopener noreferrer"&gt;Lighthouse accessibility score&lt;/a&gt; (Chrome for Developers)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.chrome.com/docs/lighthouse/agentic-browsing/accessibility-for-agents" rel="noopener noreferrer"&gt;Accessibility for agents&lt;/a&gt; (Chrome for Developers)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://playwright.dev/docs/aria-snapshots" rel="noopener noreferrer"&gt;ARIA snapshots&lt;/a&gt; (Playwright)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://apogeewatcher.com/blog/accessibility-core-web-vitals" rel="noopener noreferrer"&gt;Accessibility + Core Web Vitals: the overlooked UX wins&lt;/a&gt; (Apogee Watcher)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://apogeewatcher.com/blog/lighthouse-agentic-browsing-scoring" rel="noopener noreferrer"&gt;Lighthouse Agentic Browsing: How to rank in chatbots&lt;/a&gt; (Apogee Watcher)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://apogeewatcher.com/blog/ai-search-visibility-agencies-measure-first" rel="noopener noreferrer"&gt;Are We Visible in ChatGPT? What Agencies Can Measure First&lt;/a&gt; (Apogee Watcher)&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>seo</category>
      <category>a11y</category>
      <category>ai</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Cloudflare and PSI Automation: Challenges, Allowlists &amp; Monitoring</title>
      <dc:creator>Apogee Watcher</dc:creator>
      <pubDate>Sat, 12 Sep 2026 06:44:16 +0000</pubDate>
      <link>https://dev.to/apogeewatcher/cloudflare-and-psi-automation-challenges-allowlists-monitoring-5bka</link>
      <guid>https://dev.to/apogeewatcher/cloudflare-and-psi-automation-challenges-allowlists-monitoring-5bka</guid>
      <description>&lt;p&gt;The same client URL opened in PageSpeed Insights from a laptop often completes. Put that URL on a schedule, call the PageSpeed Insights API from a monitoring stack, or re-run Lighthouse through a headless pipeline, and the document request returns a Cloudflare challenge, a 403, or an empty error shell. The score that ends up in the ticket is not a Core Web Vitals regression. It is a security edge deciding that automation is not a visitor worth serving HTML.&lt;/p&gt;

&lt;p&gt;That contrast is the whole problem for agencies. Manual checks feel fine, so the account team trusts the green screenshot. Overnight automation red-flags the homepage, clients ask what broke, and engineering digs into LCP subparts on a page that never reached the real document. Cloudflare is doing its job. Monitoring is measuring the wrong response. What follows is how to tell those cases apart, which Cloudflare controls usually cause them, and how to allow legitimate PageSpeed Insights traffic without opening the site to every scraper on the internet.&lt;/p&gt;

&lt;p&gt;For the wider network path (DNS, TLS, CDN cache), see &lt;a href="https://apogeewatcher.com/blog/network-performance-dns-tls-http-cdn-cache-rules" rel="noopener noreferrer"&gt;Network Performance for Web Teams: DNS, TLS, HTTP, CDN, and Cache Rules&lt;/a&gt;. That guide covers where edge routing and cache hits change Time to First Byte before paint work begins. For why one-off PageSpeed Insights runs are a weak substitute for a schedule, see &lt;a href="https://apogeewatcher.com/blog/pagespeed-insights-vs-automated-monitoring-when-manual-checks-arent-enough" rel="noopener noreferrer"&gt;PageSpeed Insights vs Automated Monitoring: When Manual Checks Aren't Enough&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why PageSpeed Insights works in a browser but fails under Cloudflare automation
&lt;/h2&gt;

&lt;p&gt;PageSpeed Insights and Lighthouse need a full HTML document, then a rendered page, to compute lab metrics. An interactive browser session often looks enough like a human visitor for Cloudflare to pass the first request, especially if cookies from a prior challenge exist, JavaScript challenges can run, or the operator is on a residential network that is not already associated with bulk scraping. Scheduled and API-driven runs typically do not share that context. They arrive from data-centre ranges, use predictable automation User-Agents (including Chrome-Lighthouse strings), lack challenge cookies, and cannot complete managed challenges the way a person with a browser can.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Path&lt;/th&gt;
&lt;th&gt;Typical Cloudflare outcome&lt;/th&gt;
&lt;th&gt;What Lighthouse / PageSpeed Insights measures&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Interactive browser PageSpeed Insights / DevTools&lt;/td&gt;
&lt;td&gt;Often allowed after challenge or soft pass&lt;/td&gt;
&lt;td&gt;Real HTML and assets (when allowed)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PageSpeed Insights API / scheduled headless&lt;/td&gt;
&lt;td&gt;Challenge interstitial, 403, connection error&lt;/td&gt;
&lt;td&gt;Challenge page, error document, or failed fetch&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Monitoring tool from fixed egress IPs&lt;/td&gt;
&lt;td&gt;Blocked until IP Access or Skip rule exists&lt;/td&gt;
&lt;td&gt;Same failure modes until allowlisted&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;When the fetch fails, Google’s tooling often surfaces messages such as &lt;code&gt;ERRORED_DOCUMENT_REQUEST&lt;/code&gt; or a generic connection failure. In Cloudflare Security Events you may see Bot Fight Mode, Super Bot Fight Mode, a WAF custom rule, rate limiting, or Under Attack Mode labelled against the same URL. Treating that as an LCP incident wastes a sprint; treat it as automation that never received the origin HTML.&lt;/p&gt;

&lt;p&gt;Agencies also hit a quieter failure: the run “succeeds” but the lab screenshot shows a Cloudflare interstitial or a stripped challenge document. Scores look absurdly bad or oddly empty. Field data in PageSpeed Insights can still look normal when enough real users reach the site, which is another reason not to collapse lab and field into one narrative. For missing URL-level field metrics, see &lt;a href="https://apogeewatcher.com/blog/pagespeed-insights-no-cls-inp-for-url" rel="noopener noreferrer"&gt;When PageSpeed Insights Shows No CLS or INP for Your URL&lt;/a&gt;. For when synthetic and real-user signals should disagree on purpose, see &lt;a href="https://apogeewatcher.com/blog/when-to-use-synthetic-vs-real-user-monitoring-performance" rel="noopener noreferrer"&gt;When to Use Synthetic vs Real User Monitoring for Performance&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Which Cloudflare controls block PageSpeed Insights and Lighthouse
&lt;/h2&gt;

&lt;p&gt;Several Cloudflare products can interrupt PageSpeed Insights automation. They are not interchangeable, and some cannot be bypassed with the allowlist patterns people copy from blog posts. Matching the failed run to the right product saves a week of rewriting Largest Contentful Paint budgets on a document that never left the edge.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bot Fight Mode (free)
&lt;/h3&gt;

&lt;p&gt;Cloudflare documents that Bot Fight Mode challenges traffic matching known bot patterns and that you cannot bypass or skip it with WAF custom rules or Page Rules, because it does not run on the Ruleset Engine. If portfolio monitoring is blocked and Bot Fight Mode is on, Skip rules aimed at Chrome-Lighthouse will not save you. Cloudflare’s own guidance points teams toward Super Bot Fight Mode when they need exceptions, or toward IP Access rules that match the connecting IP before Bot Fight Mode evaluates the request.&lt;/p&gt;

&lt;h3&gt;
  
  
  Super Bot Fight Mode (Pro and above)
&lt;/h3&gt;

&lt;p&gt;This product adds configurable actions and supports Skip actions in WAF custom rules. It is the practical path when you need to allow verified bots or monitoring User-Agents while still challenging other automated traffic. Misconfigured “Definitely automated” or “Likely automated” actions still catch Lighthouse and PageSpeed Insights traffic that Cloudflare does not classify as a verified bot.&lt;/p&gt;

&lt;h3&gt;
  
  
  Under Attack Mode
&lt;/h3&gt;

&lt;p&gt;This mode raises friction for almost everyone. Community threads regularly report PageSpeed Insights failing with &lt;code&gt;ERRORED_DOCUMENT_REQUEST&lt;/code&gt; while Under Attack Mode is enabled, even when a User-Agent allowlist appears to match in the logs. Temporary attack posture and continuous performance monitoring do not coexist cleanly unless verified bots (Known Bots) are explicitly skipped from remaining security checks. Under Attack Mode fits active incidents; it is a poor permanent monitoring configuration.&lt;/p&gt;

&lt;h3&gt;
  
  
  WAF custom rules and managed rules
&lt;/h3&gt;

&lt;p&gt;Country blocks, ASN blocks, rate limits, and managed rule sets can 403 Google’s lab infrastructure or your monitoring egress. A rule that challenges “automated” traffic without an earlier Skip for known good bots will catch PageSpeed Insights. Order matters: exceptions for verified bots and monitoring IPs need to run before the block or challenge.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rate limiting and Bot Management scores
&lt;/h3&gt;

&lt;p&gt;Burst schedules across many URLs on one hostname can trip rate limits even when a single manual test works. Enterprise Bot Management customers can use score fields for finer thresholds; most agency clients on Free or Pro still need coarser Skip / IP Access patterns. When you investigate a Cloudflare block on PageSpeed Insights, open Security Events for the exact timestamp of the failed run, note the Service label, and match it to the product above before you rewrite Largest Contentful Paint budgets. Guessing “CDN is slow” from a challenged document wastes time that belongs in the security configuration, so screenshot the event for the client ticket so the zone admin sees the same evidence you used.&lt;/p&gt;

&lt;h2&gt;
  
  
  Origin versus edge: what a blocked lab run is actually measuring
&lt;/h2&gt;

&lt;p&gt;A healthy synthetic run should measure the HTML and assets your visitors receive after Cloudflare’s edge has applied caching and routing, not a challenge interstitial and not a bypass that skips the edge entirely unless that bypass is intentional. Mixing those paths without labels is what makes weekly scores look volatile when nothing in the application changed. Three measurement modes show up in agency work:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Edge as users see it. Requests go through Cloudflare with the same security posture as public traffic, except for narrow exceptions for known good lab traffic. This is the default you want for scheduled PageSpeed Insights once allowlists are correct.&lt;/li&gt;
&lt;li&gt;Challenge / block response. Automation measures Cloudflare’s security HTML or a failed document fetch. Lab metrics are invalid for Core Web Vitals decisions. Report the failure as a monitoring access issue, not as a performance regression.&lt;/li&gt;
&lt;li&gt;Origin-direct bypass. Some teams point monitors at the origin hostname or an IP Access “grey cloud” path so tests always pass. That can prove origin PHP or application latency, but it is not the same as visitor experience through the CDN. Use it as a diagnostic split, labelled clearly, not as the only portfolio score.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In our experience, the worst client reports skip those labels. One week’s “green” run used a temporary Under Attack exception; the next week’s “red” run hit Bot Fight Mode again. The narrative looks like volatility. The cause is inconsistent access to the document.&lt;/p&gt;

&lt;p&gt;Origin and edge stay honest the same way Cache-Control stays honest: name which hostname, which Cloudflare mode, and which allowlist were in effect for the run you are quoting. Pair that with fixed performance budgets so a challenge-induced score does not auto-open a “fix LCP” ticket. Budget templates live in &lt;a href="https://apogeewatcher.com/blog/performance-budget-thresholds-template" rel="noopener noreferrer"&gt;Performance Budget Thresholds Template&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Allowlists that work: verified bots, IP Access, and Skip rules
&lt;/h2&gt;

&lt;p&gt;There is no single checkbox labelled “allow PageSpeed Insights forever.” You assemble a small set of exceptions that match how Cloudflare classifies the traffic, then you verify with a scheduled re-run. The patterns below are the ones that usually hold up under Security Events review.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prefer verified / known bots over User-Agent string matching alone
&lt;/h3&gt;

&lt;p&gt;Cloudflare documents custom-rule patterns that allow search-engine and other verified bots using fields such as &lt;code&gt;cf.client.bot&lt;/code&gt; (and Bot Management fields where available). User-Agent contains &lt;code&gt;"Chrome-Lighthouse"&lt;/code&gt; rules are fragile: they are easy to spoof, easy to miss when Google changes strings, and insufficient under Under Attack Mode when the wrong Skip scope is selected. Known Bots / verified bot Skip rules for remaining WAF modules and Super Bot Fight Mode (where the plan supports them) are a stronger starting point, with monitoring-specific exceptions added only if Security Events still show blocks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use IP Access allow rules for known monitoring egress
&lt;/h3&gt;

&lt;p&gt;If your PageSpeed Insights automation or third-party monitor exits from stable IP ranges, an IP Access allow that matches the connecting IP can prevent Bot Fight Mode from firing on those requests (Cloudflare notes Bot Fight Mode will not trigger when an IP Access rule matches first). Document the ranges with the vendor and rotate them when the vendor publishes changes. Allowlisting entire cloud regions is usually too broad for the risk you are trying to reduce.&lt;/p&gt;

&lt;h3&gt;
  
  
  Move from Bot Fight Mode to Super Bot Fight Mode when you need Skip
&lt;/h3&gt;

&lt;p&gt;Free Bot Fight Mode cannot honour WAF Skip the way Super Bot Fight Mode can. Agencies stuck on Free with constant false positives on monitoring have a product constraint, not a missing regex. The realistic options are to disable Bot Fight Mode after the attack window, upgrade so Skip rules work, or accept that scheduled PageSpeed Insights on that zone will stay unreliable.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scope Skip narrowly
&lt;/h3&gt;

&lt;p&gt;A Skip that disables all remaining security for any bot-shaped request is a self-inflicted outage waiting to happen. Narrowing by hostname path if needed (public marketing URLs versus authenticated app), by verified-bot field, and by known monitoring IPs keeps the exception honest. Review Security Events after the change to confirm PageSpeed Insights is skipped for the right reason and that random scrapers are still challenged.&lt;/p&gt;

&lt;h3&gt;
  
  
  Confirm with the same automation that failed
&lt;/h3&gt;

&lt;p&gt;A manual browser pass after a rule change proves little. Re-run the scheduled job or API call that produced the original error, and only then mark the incident closed. Scheduling discipline for portfolios is covered in &lt;a href="https://apogeewatcher.com/blog/how-to-schedule-pagespeed-monitoring-test-frequency-priority-portfolio" rel="noopener noreferrer"&gt;PageSpeed Monitoring: How to Schedule Test Frequency and Priority Across Your Portfolio&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  User-Agent myths, warm-up, retries, and what not to do
&lt;/h2&gt;

&lt;p&gt;Spoofing Googlebot to “pass” Cloudflare from a monitoring host violates Google’s crawler guidelines, teaches the wrong security lesson, and still fails when Cloudflare verifies bots beyond the User-Agent string. If you need Googlebot behaviour, you are not debugging PageSpeed Insights automation; you are debugging crawl access. Turning security off globally to get a green Lighthouse score is the other common shortcut, and it trades one KPI for a real incident risk. Time-boxed Under Attack Mode, narrow Skips, and IP Access for monitors are safer than disabling Bot Fight Mode or WAF managed rules site-wide for a performance project.&lt;/p&gt;

&lt;p&gt;User-Agent allowlists help on some plans and some products, but they are not complete. They do not override Bot Fight Mode. They do not always survive Under Attack Mode. They do nothing for rate limits keyed on IP.&lt;/p&gt;

&lt;p&gt;Warm-up and retries have limits. A single warm-up request that solves a challenge in a full browser does not automatically mint cookies for a separate PageSpeed Insights API worker. Retrying a challenged URL every minute usually deepens rate-limit pain without producing a valid document, so retries fit transient network errors after allowlists are confirmed, not as a substitute for a Skip rule.&lt;/p&gt;

&lt;p&gt;Runbooks stay clearer when “tool blocked” and “site slow” stay separate. Security Events and HTTP status come first; LCP subparts come after. If the document request never returned 200 HTML from the application, the performance playbook stops and a Cloudflare configuration ticket with the client’s zone admin is the right next step.&lt;/p&gt;

&lt;h2&gt;
  
  
  How agencies should report Cloudflare blocks in client monitoring
&lt;/h2&gt;

&lt;p&gt;Clients rarely want a lecture on Ruleset Engine phases. They want to know whether the site is slow for users or whether the monitor was refused. A short script in the report usually covers it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;State the failure mode in plain language: “Scheduled PageSpeed Insights received a Cloudflare challenge / 403, so lab metrics are invalid for this run.”&lt;/li&gt;
&lt;li&gt;Attach evidence: Security Events screenshot or rule name, HTTP status, and whether field data in PageSpeed Insights still looks normal.&lt;/li&gt;
&lt;li&gt;Name the owner: client Cloudflare admin versus agency monitoring egress. Most allowlist changes require the zone owner.&lt;/li&gt;
&lt;li&gt;Record the fix: verified-bot Skip, IP Access allow, Super Bot Fight Mode change, or temporary Under Attack Mode turned off after the incident.&lt;/li&gt;
&lt;li&gt;Re-run on schedule and only then restore budget alerting for that URL.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Keep synthetic budgets armed for real regressions once access is restored. Muting an entire client because one zone had Bot Fight Mode misconfigured hides unrelated regressions; mute or annotate the affected URLs until the next clean run instead. That keeps Apogee Watcher-style portfolio schedules useful: continuous checks, early detection, clear reports, without pretending every red score is an LCP bug. If you run Apogee Watcher across many Cloudflare-fronted clients, recurring challenge failures belong on the onboarding checklist: confirm Bot Fight Mode posture, document whether Super Bot Fight Mode Skip is available, and store monitoring egress expectations with the client before you promise daily lab history.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Why does PageSpeed Insights work manually but fail on a schedule behind Cloudflare?
&lt;/h3&gt;

&lt;p&gt;Manual runs often complete challenges or arrive from networks Cloudflare treats more gently. Scheduled API and headless runs look like automation, lack challenge state, and hit Bot Fight Mode, WAF rules, or Under Attack Mode. Fix allowlists and product mode rather than only re-testing from a laptop.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can a WAF custom rule Skip Bot Fight Mode for Chrome-Lighthouse?
&lt;/h3&gt;

&lt;p&gt;No. Cloudflare documents that Bot Fight Mode cannot be bypassed with WAF custom rules or Page Rules. Super Bot Fight Mode with Skip, IP Access allows that match first, or disabling Bot Fight Mode when the attack window is over are the documented paths.&lt;/p&gt;

&lt;h3&gt;
  
  
  Should we allowlist by User-Agent or by verified bots?
&lt;/h3&gt;

&lt;p&gt;Prefer verified / Known Bots fields and stable monitoring IPs. User-Agent matching is a weak secondary signal and is easy to get wrong under Under Attack Mode.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is a green score through an origin bypass good enough for clients?
&lt;/h3&gt;

&lt;p&gt;Only as a labelled diagnostic. Visitors still hit the Cloudflare edge. Report edge-path PageSpeed Insights once security exceptions are correct.&lt;/p&gt;

&lt;h3&gt;
  
  
  What if field data looks fine but lab keeps failing?
&lt;/h3&gt;

&lt;p&gt;That pattern often means real users pass while automation is blocked, or that URL-level field metrics are missing for other reasons. Investigate Cloudflare events first, then reconcile lab versus field with your usual synthetic-versus-RUM rules.&lt;/p&gt;




&lt;p&gt;When Cloudflare blocks PageSpeed Insights automation, the monitoring problem is access, not paint timing. Diagnose the product that challenged the request, apply the narrowest Skip or IP Access that still protects the zone, and re-run the same scheduled path before you rewrite performance budgets. If you want that loop across a multi-tenant portfolio without babysitting every PageSpeed Insights tab, &lt;a href="https://apogeewatcher.com/sign-up" rel="noopener noreferrer"&gt;start a free Apogee Watcher trial&lt;/a&gt; or &lt;a href="https://apogeewatcher.com/check" rel="noopener noreferrer"&gt;run a quick check&lt;/a&gt; on a priority URL once Cloudflare allows the document through.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://developers.cloudflare.com/bots/get-started/bot-fight-mode/" rel="noopener noreferrer"&gt;Bot Fight Mode&lt;/a&gt; (Cloudflare Docs)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developers.cloudflare.com/bots/troubleshooting/false-positives/" rel="noopener noreferrer"&gt;Handle false positives from Bot Fight Mode or Super Bot Fight Mode&lt;/a&gt; (Cloudflare Docs)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developers.cloudflare.com/bots/get-started/super-bot-fight-mode/" rel="noopener noreferrer"&gt;Super Bot Fight Mode&lt;/a&gt; (Cloudflare Docs)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developers.cloudflare.com/waf/custom-rules/use-cases/allow-traffic-from-verified-bots/" rel="noopener noreferrer"&gt;Allow traffic from search engine bots and other verified bots&lt;/a&gt; (Cloudflare WAF Docs)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developers.cloudflare.com/use-cases/solutions/stop-malicious-bots/" rel="noopener noreferrer"&gt;Stop malicious bots while allowing legitimate traffic&lt;/a&gt; (Cloudflare use cases)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://community.cloudflare.com/t/pagespeed-insights-blocked-in-under-attack-mode-despite-active-allowlist-rule/791641" rel="noopener noreferrer"&gt;PageSpeed Insights blocked in Under Attack Mode despite active allowlist rule&lt;/a&gt; (Cloudflare Community)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developers.google.com/speed/docs/insights/v5/about" rel="noopener noreferrer"&gt;About PageSpeed Insights&lt;/a&gt; (Google)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://apogeewatcher.com/blog/network-performance-dns-tls-http-cdn-cache-rules" rel="noopener noreferrer"&gt;Network Performance for Web Teams: DNS, TLS, HTTP, CDN, and Cache Rules&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://apogeewatcher.com/blog/pagespeed-insights-vs-automated-monitoring-when-manual-checks-arent-enough" rel="noopener noreferrer"&gt;PageSpeed Insights vs Automated Monitoring: When Manual Checks Aren't Enough&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://apogeewatcher.com/blog/how-to-schedule-pagespeed-monitoring-test-frequency-priority-portfolio" rel="noopener noreferrer"&gt;PageSpeed Monitoring: How to Schedule Test Frequency and Priority Across Your Portfolio&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://apogeewatcher.com/blog/pagespeed-insights-no-cls-inp-for-url" rel="noopener noreferrer"&gt;When PageSpeed Insights Shows No CLS or INP for Your URL&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://apogeewatcher.com/blog/when-to-use-synthetic-vs-real-user-monitoring-performance" rel="noopener noreferrer"&gt;When to Use Synthetic vs Real User Monitoring for Performance&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://apogeewatcher.com/blog/performance-budget-thresholds-template" rel="noopener noreferrer"&gt;Performance Budget Thresholds Template&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>webperf</category>
      <category>seo</category>
    </item>
    <item>
      <title>Your SPA is leaking memory. A green Lighthouse score will not tell you</title>
      <dc:creator>Apogee Watcher</dc:creator>
      <pubDate>Fri, 11 Sep 2026 13:33:26 +0000</pubDate>
      <link>https://dev.to/apogeewatcher/your-spa-is-leaking-memory-a-green-lighthouse-score-will-not-tell-you-45d3</link>
      <guid>https://dev.to/apogeewatcher/your-spa-is-leaking-memory-a-green-lighthouse-score-will-not-tell-you-45d3</guid>
      <description>&lt;p&gt;Run PageSpeed Insights on a fresh URL and you often get a reassuring picture: Largest Contentful Paint in budget, Interaction to Next Paint acceptable, Cumulative Layout Shift quiet. Leave the same single-page application open through a working day, open drawers, filter tables, hop between client-side routes, and the tab feels heavier. Scroll stutters. Clicks queue. A force reload fixes it until the afternoon repeats the cycle. That gap is the argument: a green Lighthouse score on a cold load is one honest answer about one moment. It is not proof that memory stays flat after hundreds of interactions on the same document.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why a green Lighthouse score can hide a leaking tab
&lt;/h2&gt;

&lt;p&gt;Lighthouse, including the run inside PageSpeed Insights, measures a controlled lab visit. It loads the URL, exercises the page for a bounded window, and reports Core Web Vitals and diagnostics for that snapshot. It does not keep a browser tab alive for six hours while a user repeats the same admin workflow. It does not assert that detached DOM nodes return to zero or that event listener counts stop climbing.&lt;/p&gt;

&lt;p&gt;Memory leaks in a JavaScript single-page application are a session problem. They accumulate across route changes, modal open and close cycles, polling timers, and cached query results that never get released. The symptom is often responsiveness, not a red performance category on first paint. Teams search for "lighthouse memory leak" and find forum threads explaining that Lighthouse was never a heap profiler. That is correct, but it is only half the operational story. The other half is that production SPAs are long-lived, and your monitoring habits may still be optimised for the first load.&lt;/p&gt;

&lt;h2&gt;
  
  
  What changes when the page never reloads
&lt;/h2&gt;

&lt;p&gt;Classic multi-page sites handed memory management to navigation. Follow a link, the old document tears down, listeners go with it, and a new page starts from a clean slate. Single-page applications trade that reset for smoother transitions: the same document stays alive while JavaScript swaps views. Electron shells and embedded web views behave the same way, because the underlying page is not reloaded either.&lt;/p&gt;

&lt;p&gt;Den Odell's recent write-up on &lt;a href="https://denodell.com/blog/your-spa-is-leaking-memory-soak-test-it" rel="noopener noreferrer"&gt;frontend soak testing&lt;/a&gt; quotes a static analysis of five hundred popular React, Vue, and Angular repositories from early 2026: eighty-six percent registered a listener, timer, or subscription somewhere without a matching teardown. The leak does not need to be large. A few detached nodes per drawer open, times two hundred opens in a shift, plus a polling interval that never clears, is enough to push a tab from snappy to miserable. Backend teams learned this decades ago with overnight soak tests on servers. Front-end teams are catching up because the product shape changed.&lt;/p&gt;

&lt;h2&gt;
  
  
  The force-reload workaround teams admit in private
&lt;/h2&gt;

&lt;p&gt;Some teams schedule a hard reload of their SPA every few hours so users never reach the cliff edge. It works as a band-aid. It also signals that the app leaks badly enough that operations would rather interrupt work than fix the root cause. Support tickets that mention "leave it open all day and it slows down" are often memory pressure, even when no single Lighthouse run ever failed.&lt;/p&gt;

&lt;p&gt;That pattern is different from deploy-day regressions. A bad release can spike INP on a cold URL and show up in the next scheduled lab run. A leak might ship green on every pull request and still ruin Thursday afternoon for anyone who keeps the dashboard open. Treating force reload as policy is a clue that session-long behaviour needs its own test lane, not another argument about whether Lighthouse should have caught it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What PageSpeed Insights and Lighthouse do not run long enough to see
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Question&lt;/th&gt;
&lt;th&gt;Cold Lighthouse / PSI&lt;/th&gt;
&lt;th&gt;Long-lived SPA session&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;When does it run?&lt;/td&gt;
&lt;td&gt;Once per test, fresh profile&lt;/td&gt;
&lt;td&gt;Hours on the same document&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What fails first?&lt;/td&gt;
&lt;td&gt;LCP, INP, CLS on initial route&lt;/td&gt;
&lt;td&gt;Growing heap, listener drift, janky main thread&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Typical CI hook&lt;/td&gt;
&lt;td&gt;Budget on one URL after build&lt;/td&gt;
&lt;td&gt;Rarely covered unless you add a soak job&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;User report&lt;/td&gt;
&lt;td&gt;"Homepage is slow"&lt;/td&gt;
&lt;td&gt;"It gets worse the longer I work"&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Scheduled PageSpeed monitoring still matters for agency portfolios: it catches deploy regressions on money URLs, compares mobile and desktop lab runs, and keeps a history when a client asks what changed last Tuesday. It is the wrong tool for proving that route seventeen does not leave ninety listeners attached. Soak tests and heap snapshots answer that class of question. Mixing them up creates blind spots: green dashboards while account managers reboot the tab before a screen share.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frontend soak tests: one flow, hundreds of loops
&lt;/h2&gt;

&lt;p&gt;Odell's proposal is straightforward. Take a realistic user flow that starts and ends on the same screen, such as open a drawer and close it, or apply a filter and clear it. Run it in a loop inside a single Playwright browser context, hundreds of times, without resetting between iterations. Compare DOM node count and JavaScript event listener count before and after. If listeners monotonically increase or nodes drift upward on a round-trip flow, you have a leak signal worth investigating.&lt;/p&gt;

&lt;p&gt;Playwright end-to-end suites usually spin up a fresh context per test, which is correct for functional checks but useless for accumulation. A soak test deliberately reuses one context so each pass leaves residue in memory, the same way a real user's afternoon does. Odell packages the measurement helpers in &lt;a href="https://github.com/denodell/playwright-soak-test" rel="noopener noreferrer"&gt;playwright-soak-test&lt;/a&gt;, and the patterns below follow his article for teams planning a nightly job rather than reimplementing CDP reads from scratch.&lt;/p&gt;

&lt;h3&gt;
  
  
  DOM nodes, listeners, and compressed time with a fake clock
&lt;/h3&gt;

&lt;p&gt;Chromium exposes heap size, DOM node count, and listener count through the Chrome DevTools Protocol. A typical pattern collects garbage twice (Odell found one pass left detached React nodes visible on roughly one reading in six), then reads &lt;code&gt;Performance.getMetrics&lt;/code&gt; for &lt;code&gt;JSHeapUsedSize&lt;/code&gt;, &lt;code&gt;Nodes&lt;/code&gt;, and &lt;code&gt;JSEventListeners&lt;/code&gt;. Heap jumps on first load when lazy routes fetch code, so the soak helper warms up a few loops before recording a baseline.&lt;/p&gt;

&lt;p&gt;Assertions usually target listeners first when the bug is a &lt;code&gt;addEventListener&lt;/code&gt; without &lt;code&gt;removeEventListener&lt;/code&gt;, and node count with a fixed tolerance when detached DOM is held by object references. Readings jitter between runs, so this belongs in a nightly workflow more than on every commit. Feeds that are supposed to grow memory are poor soak candidates; round-trip UI chrome is ideal.&lt;/p&gt;

&lt;p&gt;Timers are the other large category in that repository scan, especially &lt;code&gt;setTimeout&lt;/code&gt; polling. Two hundred fast Playwright loops might only fire a poller a handful of times compared with an hour of real time. Odell's fix is to install Playwright's fake clock before navigation, pause after startup, then advance thirty seconds per loop while mocking network responses so fetches complete before the next tick. Without the mock, real network latency distorts how often the poller runs, and your test under-stresses the leak. Return payloads close to production size, too: a tiny JSON stub can hide a leak that only appears when fifty kilobytes land in cache each poll.&lt;/p&gt;

&lt;h2&gt;
  
  
  When leaks show up as Interaction to Next Paint pain
&lt;/h2&gt;

&lt;p&gt;Interaction to Next Paint measures responsiveness on real interactions: clicks, taps, and key presses until the next paint. It does not read heap size directly. Memory pressure still shows up there because a bloated tab spends more time in garbage collection and main-thread work, so the same button click waits longer. Event handlers attached to detached subtrees can fire at surprising times. Layout thrash from thousands of hidden nodes makes presentation delay worse.&lt;/p&gt;

&lt;p&gt;If INP on money flows is fine in a cold lab run but support hears "after lunch it feels sticky," suspect session accumulation before you chase another image optimisation. Our guide on &lt;a href="https://apogeewatcher.com/blog/understanding-inp-newest-core-web-vital?utm_source=hashnode&amp;amp;utm_medium=referral&amp;amp;utm_campaign=hashnode-your-spa-is-leaking-memory-green-lighthouse-will-not-tell-you" rel="noopener noreferrer"&gt;Understanding INP&lt;/a&gt; walks through what INP captures and how field scoring works. Pair that mental model with soak tests on the flows that repeat all day, not only the homepage once.&lt;/p&gt;

&lt;h2&gt;
  
  
  Soft navigations keep the same document alive
&lt;/h2&gt;

&lt;p&gt;Chrome 151's soft-navigation work makes route changes inside an SPA easier to measure per transition, but it does not reload the document. History updates, views swap, and the same JavaScript heap remains. That is good for user experience and good for performance engineers who finally get route-shaped metrics. It also means cleanup bugs survive across "pages" the user perceives.&lt;/p&gt;

&lt;p&gt;When a client-side route change does not tear down the previous view's listeners, soft navigations can look fine on paint timings while memory still climbs. Preparing for those entries is a measurement story; preventing leaks is an implementation story. Our write-up on &lt;a href="https://apogeewatcher.com/blog/soft-navigations-chrome-151-prepare-measure?utm_source=hashnode&amp;amp;utm_medium=referral&amp;amp;utm_campaign=hashnode-your-spa-is-leaking-memory-green-lighthouse-will-not-tell-you" rel="noopener noreferrer"&gt;soft navigations in Chrome 151&lt;/a&gt; covers what to detect and how Interaction Contentful Paint relates to Largest Contentful Paint on route changes. Soak tests still matter because they stress the lifecycle your users actually repeat.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where scheduled monitoring still belongs
&lt;/h2&gt;

&lt;p&gt;Soak tests belong next to your end-to-end suite: nightly or on main, scoped to flows that round-trip cleanly. Lighthouse in continuous integration belongs on cold URLs and budgets you care about at deploy time. Scheduled PageSpeed monitoring belongs on the portfolio list you would put in a client QBR. Those layers overlap in spirit because each one asks whether the product is fast enough, but none of them replaces the others.&lt;/p&gt;

&lt;p&gt;We are not arguing against lab budgets on checkout because you added a drawer soak test. We are arguing against treating a green Lighthouse icon as proof that nothing leaks. Agencies managing dozens of SPAs need both: regression detection on known URLs for INP and LCP, and at least one soak flow per app that mirrors how staff use the admin all day. TanStack Table tree-shaking and opt-in features address a different INP lever (less JavaScript up front). Memory leaks are the slow drip after the feature shipped.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Can Lighthouse or PageSpeed Insights detect memory leaks in an SPA?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No. They report lab Core Web Vitals and diagnostics for a short, fresh visit. They do not track heap growth or listener counts across hundreds of client-side navigations. Use Chrome DevTools Memory snapshots or an automated soak test for that class of bug.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is a frontend soak test?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A scripted user flow repeated many times in one browser context, with DOM node and listener counts compared before and after. It mimics how a long work session stresses the same document, compressed into minutes. Den Odell's &lt;a href="https://denodell.com/blog/your-spa-is-leaking-memory-soak-test-it" rel="noopener noreferrer"&gt;soak test article&lt;/a&gt; and &lt;a href="https://github.com/denodell/playwright-soak-test" rel="noopener noreferrer"&gt;playwright-soak-test&lt;/a&gt; repository are practical starting points.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How is a soak test different from normal Playwright end-to-end tests?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;End-to-end tests reset browser state so each case is isolated. Soak tests deliberately do not reset, because the bug only appears when state accumulates. Keep functional tests fast and isolated; run soak tests on a schedule with looser timing tolerances.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does fixing memory leaks replace monitoring Interaction to Next Paint?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No. Leak fixes help session-long responsiveness, but deploy regressions, third-party scripts, and network changes still move INP on cold loads. Monitoring money URLs on a schedule catches those shifts even when soak tests pass.&lt;/p&gt;

&lt;h2&gt;
  
  
  A practical split for agency SPAs
&lt;/h2&gt;

&lt;p&gt;A useful default is three lanes. Cold lab budgets on the URLs clients quote in audits. A soak test on one round-trip flow per critical app, failing when listeners or nodes drift. Scheduled field and lab monitoring on the same money routes so you notice when Tuesday's deploy changes INP even if memory was already flat.&lt;/p&gt;

&lt;p&gt;If you manage multiple client SPAs and want scheduled PageSpeed runs with alerts when INP or LCP cross budgets, that is the lane we built Apogee Watcher for. It will not replace a soak test, and a soak test will not replace watching production URLs after each release. &lt;a href="https://apogeewatcher.com/sign-up?utm_source=hashnode&amp;amp;utm_medium=referral&amp;amp;utm_campaign=hashnode-your-spa-is-leaking-memory-green-lighthouse-will-not-tell-you" rel="noopener noreferrer"&gt;Start a free trial&lt;/a&gt; with the routes you already report, then add the nightly soak job your admin users have been simulating with forced reloads.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://denodell.com/blog/your-spa-is-leaking-memory-soak-test-it" rel="noopener noreferrer"&gt;Your SPA Is Leaking Memory. Soak Test It&lt;/a&gt; (Den Odell)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/denodell/playwright-soak-test" rel="noopener noreferrer"&gt;playwright-soak-test&lt;/a&gt; (Den Odell; Playwright fixture from the soak test article)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.chrome.com/docs/devtools/recorder" rel="noopener noreferrer"&gt;Record, replay and measure user flows&lt;/a&gt; (Chrome DevTools; related lab tooling context)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://apogeewatcher.com/blog/understanding-inp-newest-core-web-vital" rel="noopener noreferrer"&gt;Understanding INP: The Newest Core Web Vital and Why It Matters&lt;/a&gt; (Apogee Watcher)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://apogeewatcher.com/blog/soft-navigations-chrome-151-prepare-measure" rel="noopener noreferrer"&gt;Soft Navigations in Chrome 151: How to Prepare and What to Measure&lt;/a&gt; (Apogee Watcher)&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webperf</category>
      <category>corewebvitals</category>
      <category>agency</category>
      <category>seo</category>
    </item>
    <item>
      <title>Cache-Control Headers for Web Performance: CDN and Browser Caching That Sticks</title>
      <dc:creator>Apogee Watcher</dc:creator>
      <pubDate>Fri, 11 Sep 2026 13:16:59 +0000</pubDate>
      <link>https://dev.to/apogeewatcher/cache-control-headers-for-web-performance-cdn-and-browser-caching-that-sticks-1ckb</link>
      <guid>https://dev.to/apogeewatcher/cache-control-headers-for-web-performance-cdn-and-browser-caching-that-sticks-1ckb</guid>
      <description>&lt;p&gt;The CDN is enabled. The origin sends sensible browser caching headers. A lab run on the priority URL still shows a slow document Time to First Byte and repeat views that behave like cold loads. In our experience the gap is rarely “caching is off” as a single switch. It is a mismatch between what the origin allows, what the CDN dashboard overrides, and which layer the browser actually reuses on the next navigation. Cache-Control is the contract that ties those layers together. When the contract is vague or copied from a generic template, performance work does not stick past the next platform default or purge.&lt;/p&gt;

&lt;p&gt;What follows is a content-type guide for teams who already understand DNS, TLS, and edge routing from &lt;a href="https://apogeewatcher.com/blog/network-performance-dns-tls-http-cdn-cache-rules" rel="noopener noreferrer"&gt;Network Performance for Web Teams: DNS, TLS, HTTP, CDN, and Cache Rules&lt;/a&gt;. That piece explains where cache hits change TTFB on the request path. Here we focus on the header strings that make those hits legal, the CDN defaults that undo them, and how to prove the policy held after deploy with scheduled lab runs.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Cache-Control changes on the path to first byte and repeat views
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;Cache-Control&lt;/code&gt; response header holds directives that tell browsers and shared caches (CDNs, reverse proxies) whether they may store a response, how long it stays fresh, and whether they must revalidate before reuse. Freshness is measured from when the response was generated at the origin, adjusted by any &lt;code&gt;Age&lt;/code&gt; header added by intermediaries. A directive on the HTML document can therefore change first-byte wait on a CDN miss, while directives on CSS, JavaScript, fonts, and images change how much work repeats on the second view without touching the document request at all.&lt;/p&gt;

&lt;p&gt;The directives that matter most for web performance work are &lt;code&gt;max-age&lt;/code&gt; (fresh lifetime in seconds), &lt;code&gt;s-maxage&lt;/code&gt; (fresh lifetime for shared caches only), &lt;code&gt;public&lt;/code&gt; and &lt;code&gt;private&lt;/code&gt; (whether a shared cache may store the response), &lt;code&gt;no-cache&lt;/code&gt; (store but revalidate before use), &lt;code&gt;no-store&lt;/code&gt; (do not store), &lt;code&gt;immutable&lt;/code&gt; (while fresh, skip revalidation on reload), &lt;code&gt;must-revalidate&lt;/code&gt;, and extension directives such as &lt;code&gt;stale-while-revalidate&lt;/code&gt; and &lt;code&gt;stale-if-error&lt;/code&gt;. &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Cache-Control" rel="noopener noreferrer"&gt;MDN documents each directive&lt;/a&gt;; &lt;a href="https://www.rfc-editor.org/rfc/rfc9111.html" rel="noopener noreferrer"&gt;RFC 9111&lt;/a&gt; is the normative reference when you need to settle a dispute between engineering and the CDN vendor.&lt;/p&gt;

&lt;p&gt;Treat every response as belonging to a content class before you copy a header string from a blog post. HTML entry points, fingerprinted static bundles, unversioned images, authenticated account pages, and public JSON APIs need different policies. The performance win comes from aligning the class, the origin header, the CDN rule, and your purge discipline so they still agree on the live hostname after release.&lt;/p&gt;

&lt;h2&gt;
  
  
  Browser cache versus CDN cache: two layers that need different directives
&lt;/h2&gt;

&lt;p&gt;Browser caching headers govern the copy on the device. CDN cache rules govern the copy at the edge. They read the same &lt;code&gt;Cache-Control&lt;/code&gt; line but apply different parts of it. &lt;code&gt;s-maxage&lt;/code&gt; applies only to shared caches and overrides &lt;code&gt;max-age&lt;/code&gt; for them when both are present. &lt;code&gt;private&lt;/code&gt; keeps a response out of shared caches while still allowing a browser store. &lt;code&gt;immutable&lt;/code&gt; affects reload behaviour for static assets in the browser. Confusing the two layers produces tickets that say “we purged the CDN but nothing changed,” because the team purged the edge while the browser still held an old document, or vice versa.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Who stores&lt;/th&gt;
&lt;th&gt;Typical levers&lt;/th&gt;
&lt;th&gt;Effect on cold TTFB&lt;/th&gt;
&lt;th&gt;Effect on repeat views / LCP&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Browser&lt;/td&gt;
&lt;td&gt;Returning visitor&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;max-age&lt;/code&gt;, &lt;code&gt;immutable&lt;/code&gt;, &lt;code&gt;no-cache&lt;/code&gt; + validators&lt;/td&gt;
&lt;td&gt;Small on first visit&lt;/td&gt;
&lt;td&gt;Large when static assets skip full downloads&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CDN (shared cache)&lt;/td&gt;
&lt;td&gt;Any visitor hitting that PoP&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;s-maxage&lt;/code&gt;, &lt;code&gt;public&lt;/code&gt;, origin cacheability, purge tags&lt;/td&gt;
&lt;td&gt;Large on cache hit for HTML and assets&lt;/td&gt;
&lt;td&gt;Smaller origin load; stable edge latency&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Origin&lt;/td&gt;
&lt;td&gt;Source of truth&lt;/td&gt;
&lt;td&gt;App framework defaults, &lt;code&gt;CDN-Cache-Control&lt;/code&gt; on some stacks&lt;/td&gt;
&lt;td&gt;Defines miss cost&lt;/td&gt;
&lt;td&gt;N/A until next request&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A useful policy document names the content class, the origin header, the CDN behaviour when the header is absent, and who purges what on deploy. Without that table, agencies inherit “cache everything” dashboard templates that fight the application’s HTML strategy or strip &lt;code&gt;ETag&lt;/code&gt; headers the framework relies on for cheap &lt;code&gt;304 Not Modified&lt;/code&gt; responses.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cache-Control for fingerprinted CSS, JavaScript, fonts, and images
&lt;/h2&gt;

&lt;p&gt;Static assets whose URLs change when content changes should be cached aggressively at both browser and CDN. The filename is the versioning mechanism. A stylesheet served as &lt;code&gt;/assets/app.9f1c2d4e.css&lt;/code&gt; can safely carry a one-year freshness lifetime because the next deploy publishes &lt;code&gt;/assets/app.b3e8a1f0.css&lt;/code&gt; and the HTML entry point references the new name.&lt;/p&gt;

&lt;p&gt;Recommended pattern for hashed or fingerprinted files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;Cache-Control: public, max-age=31536000, immutable

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;immutable&lt;/code&gt; directive, defined in &lt;a href="https://www.rfc-editor.org/rfc/rfc8246.html" rel="noopener noreferrer"&gt;RFC 8246&lt;/a&gt;, tells clients not to send conditional revalidation requests while the response is fresh. That matters on hard reloads: without &lt;code&gt;immutable&lt;/code&gt;, browsers may still ask the server whether &lt;code&gt;app.9f1c2d4e.css&lt;/code&gt; changed even though the URL encodes the revision. For performance-sensitive sites, those avoidable round trips show up as extra connection work before Largest Contentful Paint can use a cached font or script.&lt;/p&gt;

&lt;p&gt;Do not put &lt;code&gt;immutable&lt;/code&gt; on unversioned paths such as &lt;code&gt;/styles/main.css&lt;/code&gt; or &lt;code&gt;/logo.png&lt;/code&gt; unless your release process never overwrites the same URL. If the URL is stable, use a shorter &lt;code&gt;max-age&lt;/code&gt; plus &lt;code&gt;ETag&lt;/code&gt; or &lt;code&gt;Last-Modified&lt;/code&gt; validators so updates propagate without waiting a year. &lt;a href="https://web.dev/articles/uses-long-cache-ttl" rel="noopener noreferrer"&gt;Google’s guidance on efficient cache lifetimes&lt;/a&gt; aligns with the fingerprinted-file rule: long TTLs belong where the URL changes with the bytes.&lt;/p&gt;

&lt;p&gt;After you set long TTLs at the origin, confirm the CDN is allowed to store those responses. Some platforms require &lt;code&gt;public&lt;/code&gt; explicitly. Some honour a separate &lt;code&gt;CDN-Cache-Control&lt;/code&gt; or vendor-specific override. Inspect &lt;code&gt;Age&lt;/code&gt;, &lt;code&gt;CF-Cache-Status&lt;/code&gt;, &lt;code&gt;X-Cache&lt;/code&gt;, or the equivalent on a CSS or font request in production, not only on HTML.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cache-Control for HTML documents agencies actually ship
&lt;/h2&gt;

&lt;p&gt;HTML is the map to every other asset. If the browser or CDN serves stale HTML, it may point at old bundle names even when the new files already sit on the origin. Most delivery teams therefore want HTML to revalidate often while still allowing the CDN to absorb traffic for anonymous pages.&lt;/p&gt;

&lt;p&gt;Common patterns:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Revalidate every use (good default for many marketing sites):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;Cache-Control: no-cache
ETag: "build-20260910-abc123"

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;no-cache&lt;/code&gt; does not mean “do not cache.” It means the cache must validate with the origin before reuse. With a matching &lt;code&gt;ETag&lt;/code&gt;, validation is a small &lt;code&gt;304 Not Modified&lt;/code&gt; instead of a full document download. That keeps HTML current without abandoning bandwidth savings.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Short browser freshness, longer edge TTL, background refresh:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;Cache-Control: public, max-age=0, s-maxage=60, stale-while-revalidate=300, stale-if-error=600

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Browsers treat the document as stale immediately and revalidate. The CDN may serve a fresh copy for sixty seconds and continue serving stale responses briefly while it revalidates in the background. This pattern can lower origin load during traffic spikes if your content model tolerates short edge staleness on public pages.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Personalised or authenticated HTML:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;Cache-Control: private, no-store

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or, when the response is user-specific but you still want browser revalidation without CDN storage:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;Cache-Control: private, no-cache

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Never mark personalised HTML &lt;code&gt;public&lt;/code&gt; at the CDN unless you have deliberate edge logic that varies the cache key safely. &lt;code&gt;Vary: Cookie&lt;/code&gt; without a tight vary set often collapses hit ratio to zero. Wrong HTML caching creates correctness incidents that outweigh any TTFB improvement.&lt;/p&gt;

&lt;p&gt;When you deploy new HTML that references new asset hashes, purge or revalidate HTML at the CDN if your policy allows edge caching at all. Serving cached HTML that still points at removed bundles is a common post-release failure mode that looks like a performance regression in Lighthouse even though the new files are fast.&lt;/p&gt;

&lt;h2&gt;
  
  
  CDN defaults and dashboard rules that undo your header policy
&lt;/h2&gt;

&lt;p&gt;Agencies often enable a CDN before origin headers are deliberate. Vendors ship attractive defaults: cache all static extensions for a month, “standard” caching for HTML, ignore certain origin headers, or respect only cache rules defined in the dashboard. Those defaults are a starting point, not a performance policy.&lt;/p&gt;

&lt;p&gt;Defaults we see cause repeat TTFB and LCP pain:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Mistake&lt;/th&gt;
&lt;th&gt;What breaks&lt;/th&gt;
&lt;th&gt;What to check on the live URL&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;CDN caches HTML with a long TTL while origin says &lt;code&gt;no-cache&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Stale pages, wrong asset references after deploy&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;CF-Cache-Status&lt;/code&gt; / &lt;code&gt;X-Cache&lt;/code&gt; on &lt;code&gt;/&lt;/code&gt; and a template URL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Origin sends &lt;code&gt;Cache-Control: private&lt;/code&gt; but team expects edge hits&lt;/td&gt;
&lt;td&gt;Every request becomes an origin fetch&lt;/td&gt;
&lt;td&gt;Response headers on document request&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;“Cache static file types” rule bypasses &lt;code&gt;immutable&lt;/code&gt; fingerprint policy&lt;/td&gt;
&lt;td&gt;Unnecessary revalidation or wrong TTL per extension&lt;/td&gt;
&lt;td&gt;Headers on &lt;code&gt;.js&lt;/code&gt;, &lt;code&gt;.css&lt;/code&gt;, and font files&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Blanket purge on every CMS save&lt;/td&gt;
&lt;td&gt;Hit ratio collapses; TTFB spikes for a day&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;Age&lt;/code&gt; header trend across scheduled runs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;Vary: Cookie&lt;/code&gt; on anonymous pages&lt;/td&gt;
&lt;td&gt;Edge refuses to share entries&lt;/td&gt;
&lt;td&gt;Cache key documentation from vendor&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Flexible SSL or redirect loops at edge&lt;/td&gt;
&lt;td&gt;TTFB rises before cache policy matters&lt;/td&gt;
&lt;td&gt;Redirect count in waterfall (see post 62)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Dashboard rules should echo origin intent, not fight it. If the application sets &lt;code&gt;CDN-Cache-Control&lt;/code&gt; or vendor-specific surrogate headers, document which header wins when both are present. After any CDN migration, re-audit the same priority URLs you used for the previous vendor. Rules do not transfer verbatim between Cloudflare, Fastly, Akamai, and CloudFront.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Cache-Control headers show up in TTFB and LCP lab runs
&lt;/h2&gt;

&lt;p&gt;Time to First Byte in &lt;a href="https://pagespeed.web.dev/" rel="noopener noreferrer"&gt;PageSpeed Insights&lt;/a&gt; and Lighthouse reflects how long the navigation request waited for the first byte of the HTML response. When the CDN serves a fresh document from cache, TTFB often drops sharply compared with an origin miss. When HTML is &lt;code&gt;private, no-store&lt;/code&gt; or bypasses the edge, TTFB still includes origin compute and PoP-to-origin latency even if static assets are well cached.&lt;/p&gt;

&lt;p&gt;Largest Contentful Paint inherits that document delay and then adds how quickly the LCP resource itself arrives. A hero image with a long &lt;code&gt;max-age&lt;/code&gt; at the CDN may paint fast on repeat views while the first view still waits on HTML generation. Conversely, perfect HTML caching cannot fix LCP if the LCP image lives at an unversioned URL with a five-minute TTL and the CDN misses every time.&lt;/p&gt;

&lt;p&gt;Practical reading order in lab tools:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Document request: TTFB, cache status headers, redirect count.&lt;/li&gt;
&lt;li&gt;LCP element request: cache hit or miss, protocol, priority hints.&lt;/li&gt;
&lt;li&gt;Render-blocking CSS and font requests: are they fingerprinted with long TTLs or re-fetching each view?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Pair a cold run with a repeat view when your tool supports it. Cold exposes DNS, TLS, and first miss behaviour. Repeat exposes whether browser caching headers actually removed duplicate downloads. For operational thresholds on the same URLs, set &lt;a href="https://apogeewatcher.com/blog/performance-budget-thresholds-template" rel="noopener noreferrer"&gt;performance budget thresholds&lt;/a&gt; that include TTFB and LCP, not only the Performance score.&lt;/p&gt;

&lt;p&gt;Once first byte and paint are acceptable, the LCP work in &lt;a href="https://apogeewatcher.com/blog/quick-way-to-fix-lcp" rel="noopener noreferrer"&gt;A Quick Way to Fix LCP: Four Changes That Cut Time to Paint&lt;/a&gt; still matters. Cache-Control removes avoidable network round trips; it does not shrink an oversized hero file or late-discovered LCP candidate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Verify Cache-Control on live URLs after every deploy
&lt;/h2&gt;

&lt;p&gt;Header policy is only real on the public hostname users hit. Staging often lacks the CDN overlay or sends different headers from the production origin. After each deploy, cache rule edit, or CMS plugin that touches headers, verify the live response rather than assuming the dashboard screenshot still matches production.&lt;/p&gt;

&lt;p&gt;Checklist we use on client sites:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Document URL:&lt;/strong&gt; homepage plus one high-intent template (product, pricing, article).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Representative static asset:&lt;/strong&gt; hashed JS or CSS referenced by that HTML.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LCP resource:&lt;/strong&gt; image or video request from the same lab run.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cache status:&lt;/strong&gt; &lt;code&gt;Age&lt;/code&gt;, vendor hit/miss header, and the full &lt;code&gt;Cache-Control&lt;/code&gt; line.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Validators:&lt;/strong&gt; &lt;code&gt;ETag&lt;/code&gt; or &lt;code&gt;Last-Modified&lt;/code&gt; present where you expect revalidation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compare to policy doc:&lt;/strong&gt; content class, intended header, CDN rule, purge owner.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Export the header set into the ticket or client report so the next engineer does not re-discover the same miss. A single manual check catches the first mistake. It does not prove the CDN still hits next Thursday after a content editor triggers a purge storm.&lt;/p&gt;

&lt;p&gt;Put priority URLs on &lt;a href="https://apogeewatcher.com/blog/how-to-schedule-pagespeed-monitoring-test-frequency-priority-portfolio" rel="noopener noreferrer"&gt;scheduled PageSpeed monitoring&lt;/a&gt; with device splits that match the audience. Apogee Watcher stores lab payloads over time so you can see TTFB and LCP drift after edge changes without someone opening PageSpeed Insights from memory. That layers onto your CDN vendor; it does not replace header configuration or purge discipline. For why one-off lab runs are insufficient proof, see &lt;a href="https://apogeewatcher.com/blog/pagespeed-insights-vs-automated-monitoring-when-manual-checks-arent-enough" rel="noopener noreferrer"&gt;PageSpeed Insights vs Automated Monitoring: When Manual Checks Aren't Enough&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;What is the difference between &lt;code&gt;no-cache&lt;/code&gt; and &lt;code&gt;no-store&lt;/code&gt;?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;no-cache&lt;/code&gt; allows storage but requires validation before reuse. Browsers and CDNs may keep a copy and often answer with &lt;code&gt;304 Not Modified&lt;/code&gt; when the &lt;code&gt;ETag&lt;/code&gt; still matches. &lt;code&gt;no-store&lt;/code&gt; forbids storing the response anywhere. Use &lt;code&gt;no-cache&lt;/code&gt; for HTML that must stay current but can revalidate cheaply. Use &lt;code&gt;no-store&lt;/code&gt; for sensitive account or payment flows where persistence is unacceptable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When should we use &lt;code&gt;immutable&lt;/code&gt;?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use &lt;code&gt;immutable&lt;/code&gt; only on fingerprinted static assets where the URL changes when the bytes change. Pair it with a long &lt;code&gt;max-age&lt;/code&gt;, commonly &lt;code&gt;31536000&lt;/code&gt; seconds. Do not use it on HTML or on unversioned files you overwrite in place.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does &lt;code&gt;max-age=0&lt;/code&gt; disable caching?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No. It marks the response as immediately stale, which forces revalidation behaviour similar in practice to &lt;code&gt;no-cache&lt;/code&gt; for many caches, but the directives are not identical in every intermediary. Be explicit: choose &lt;code&gt;no-cache&lt;/code&gt; when you want validation semantics, or &lt;code&gt;no-store&lt;/code&gt; when you want no persistence.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why did TTFB improve in WebPageTest but not in PageSpeed Insights?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Tools use different locations, cache states, and throttling. A hit from one PoP near the test agent does not prove global behaviour. Align test location with audience geography and inspect cache headers on the document request in both tools before closing the ticket.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Should APIs use the same Cache-Control as HTML?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Public read-heavy JSON can use short browser &lt;code&gt;max-age&lt;/code&gt; with longer &lt;code&gt;s-maxage&lt;/code&gt; and &lt;code&gt;stale-while-revalidate&lt;/code&gt; when responses are identical for all users. Authenticated or user-specific APIs usually need &lt;code&gt;private&lt;/code&gt; or &lt;code&gt;no-store&lt;/code&gt;. Treat each endpoint as its own content class.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We purged the CDN. Why do clients still see old CSS?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Purging the edge does not clear browser caches. If CSS URLs are not fingerprinted, visitors may keep an old file until &lt;code&gt;max-age&lt;/code&gt; expires. Prefer hashed filenames for bundles and purge HTML if it still references retired names.&lt;/p&gt;

&lt;h2&gt;
  
  
  Put header policy on the same schedule as performance budgets
&lt;/h2&gt;

&lt;p&gt;Pick one priority URL where TTFB or LCP still misses budget. Capture the live &lt;code&gt;Cache-Control&lt;/code&gt; lines on HTML, the LCP asset, and one fingerprinted bundle. Fix the largest layer mismatch first: origin header, CDN rule, or purge process. Re-run lab from a region that matches traffic, then add the URL to a weekly schedule so the next header regression is visible before the client forwards a screenshot.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://apogeewatcher.com/sign-up" rel="noopener noreferrer"&gt;Start a free trial&lt;/a&gt; or &lt;a href="https://apogeewatcher.com/check" rel="noopener noreferrer"&gt;run a free PageSpeed check&lt;/a&gt; on the URLs you care about, then keep the same pages on a portfolio schedule after you fix Cache-Control for web performance.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Cache-Control" rel="noopener noreferrer"&gt;Cache-Control header (MDN)&lt;/a&gt; (Mozilla)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.rfc-editor.org/rfc/rfc9111.html" rel="noopener noreferrer"&gt;RFC 9111: HTTP Caching&lt;/a&gt; (IETF)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.rfc-editor.org/rfc/rfc8246.html" rel="noopener noreferrer"&gt;RFC 8246: HTTP Immutable Responses&lt;/a&gt; (IETF)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://web.dev/articles/uses-long-cache-ttl" rel="noopener noreferrer"&gt;Uses efficient cache lifetimes on static assets&lt;/a&gt; (web.dev)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://apogeewatcher.com/blog/network-performance-dns-tls-http-cdn-cache-rules" rel="noopener noreferrer"&gt;Network Performance for Web Teams: DNS, TLS, HTTP, CDN, and Cache Rules&lt;/a&gt; (Apogee Watcher)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://apogeewatcher.com/blog/performance-budget-thresholds-template" rel="noopener noreferrer"&gt;Performance Budget Thresholds Template&lt;/a&gt; (Apogee Watcher)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://apogeewatcher.com/blog/quick-way-to-fix-lcp" rel="noopener noreferrer"&gt;A Quick Way to Fix LCP: Four Changes That Cut Time to Paint&lt;/a&gt; (Apogee Watcher)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://apogeewatcher.com/blog/how-to-schedule-pagespeed-monitoring-test-frequency-priority-portfolio" rel="noopener noreferrer"&gt;How to Schedule PageSpeed Monitoring: Test Frequency and Priority for Your Portfolio&lt;/a&gt; (Apogee Watcher)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://apogeewatcher.com/blog/pagespeed-insights-vs-automated-monitoring-when-manual-checks-arent-enough" rel="noopener noreferrer"&gt;PageSpeed Insights vs Automated Monitoring: When Manual Checks Aren't Enough&lt;/a&gt; (Apogee Watcher)&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>webperf</category>
      <category>seo</category>
    </item>
  </channel>
</rss>
