SPAs and Core Web Vitals: What Actually Counts

Since the Web Vitals initiative launched, one of the most frequent—and most nuanced—questions has been how Core Web Vitals apply to single-page applications (SPAs). The short answer is that the metrics measure user experience, not technology. Google has no preference for SPAs over multi-page applications (MPAs); both architectures can deliver high-quality experiences, and the Core Web Vitals are designed to reflect that reality.

The complexity arises because an SPA changes the meaning of terms like "page load" and "navigation." In an MPA, each route change is a full document load, which naturally resets the measurement window. In an SPA, the initial HTML document loads once, and subsequent route changes are handled via JavaScript, often updating the URL without a full reload. This architectural difference requires careful interpretation of how Core Web Vitals are reported.

Core Web Vitals in a Single-Page App

For the initial load of an SPA, the process is identical to an MPA: the browser requests the HTML document and the metrics are measured from that navigation start. The key differences appear on subsequent client-side route transitions.

  • Largest Contentful Paint (LCP) is tied to the first meaningful paint after a navigation. In an SPA, a soft navigation—a URL change without a document reload—is not a separate navigation from the browser's perspective. Historical implementations of LCP typically report only the LCP from the initial page load. However, modern performance APIs are evolving to handle this.
  • First Input Delay (FID) and Interaction to Next Paint (INP) measure responsiveness to user input. These are not tied to navigation boundaries. In an SPA, input events on one "page" can affect the responsiveness score of the next route if the JavaScript processing is slow.
  • Cumulative Layout Shift (CLS) measures visual stability over the entire lifespan of the page, not just a single navigation. In an SPA, a layout shift that happens five minutes into a session, triggered by a slow route render, will count against the CLS metric for that page load.

The practical consequence is that a poorly optimized SPA can accumulate poor CLS and INP scores over a long session, even if individual route transitions are fast. Core Web Vitals are designed to penalize jank and layout instability wherever they occur on a page, and an SPA effectively has one long "page" per document load.

The browser's Performance Timeline treats an SPA's client-side route changes as same-document navigations. Certain PerformanceObserver entries, such as largest-contentful-paint and layout-shift, are dispatched for the entire document lifetime unless the page does a full reload.

There is no built-in mechanism in the core Web Vitals APIs that automatically resets LCP or CLS when the URL changes via history.pushState. This means teams measuring Core Web Vitals with the standard web-vitals JavaScript library must handle the reset themselves. The library's onCLS and onLCP functions are designed to report the final values only, but they also expose a session or navigation scoping option that can be used to attribute metrics to individual route changes in an SPA.

For field data, Google's Chrome User Experience Report (CrUX) treats a user's entire time on a single document as one page load. If a user spends an hour in an SPA and never triggers a full reload, the CrUX entry for that URL reflects the whole session's metrics. Route-specific field data is only possible if the SPA sends a new page view to analytics for each soft navigation, which the CrUX data model does not inherently support.

What a Correct SPA Implementation Looks Like

A high-performing SPA should not rely on the initial HTML document to deliver all content and then fetch additional resources lazily on every route change. Instead, the goal is to preload or prefetch critical assets so that soft navigations are nearly instant. Even with an optimized setup, certain technical realities remain.

  • LCP on soft navigation is measured when the new route's main content becomes visible. If the router delays rendering until data fetches complete, the LCP for that route's paint point is late.
  • CLS on route transitions can be worsened by dynamic content injection or by fallback loading spinners that shift the layout when they are replaced with real content.
  • INP and FID correlate with long tasks. A heavy JavaScript bundle executed during a soft navigation can block the main thread and make the next route feel unresponsive.

In practice, a well-built SPA can perform as well as an MPA on Core Web Vitals, but it requires discipline around code-splitting, prefetching, and minimizing layout thrash during client-side renders. The metric definitions do not inherently handicap SPAs; they simply measure the user-visible quality throughout the document's lifetime.

For teams tracking Core Web Vitals in an SPA, the recommended approach is to log metrics on every soft navigation so that regressions can be traced to a specific route change. The web-vitals library supports this via its attribution and navigation scoping. Relying solely on the initial page-load values will hide the performance characteristics of the SPA's more interactive phases.

The Chrome team's stance is that Core Web Vitals should never dictate which architecture to use. The metrics are purposefully agnostic to how the underlying rendering happens. A site is measured by how its users experience paint speed, stability, and responsiveness—regardless of whether that is served by a classic server-rendered MPA or a fully client-rendered SPA.

Barry Pollard

How SPA architectures shape Core Web Vitals

Single-page applications (SPAs) present a perennial challenge for performance measurement: the traditional Core Web Vitals metrics were built around full page loads, not the client-side route transitions that define the SPA model. A page that swaps content and updates the URL in the address bar triggers no reset of metric values—the measurement keeps pointing at the URL from the initial navigation.

That is changing. Chrome 151 ships new APIs designed to extend Core Web Vitals across SPA route changes. As of August 2026, support is just beginning to appear in measurement libraries like web-vitals, RUM platforms, and DevTools. The Chrome User Experience Report (CrUX) has no integration timeline yet, and other browser engines do not support the APIs, meaning cross-browser SPA measurement still falls back to full page loads.

Defining a "soft navigation"

The difficulty is not technical but definitional. There is no standardized SPA architecture. Routing libraries differ on when and how URLs change: some update the URL only for full content swaps, others for minor UI state changes; some use the History API, others rely on hash changes, and some don't touch the URL at all. Content can load synchronously in one JavaScript task or trickle in asynchronously across several. Some SPAs fetch from the network on every route, while others preload everything so transitions resolve from memory instantly.

Without reliable heuristics for what counts as a "real" route change, retrofitting existing metrics onto SPA transitions would corrupt the data rather than clarify it. The Soft Navigation work addresses this with two new APIs. The PerformanceSoftNavigation interface defines a soft navigation as a user interaction that produces both a paint and a URL change, which gives a framework-agnostic boundary for splitting the performance timeline and measuring CLS and INP per navigation. The InteractionContentfulPaint API captures contentful paints following an interaction, enabling FCP and LCP measurement for those soft navigations.

Taken together, the two APIs let Core Web Vitals span both full page loads and soft navigations. It is important to expect different numbers across those navigation types. A soft navigation carries existing rendered content forward, much like a cached page load but even more extreme since some content never unloads. The APIs also only count newly painted elements: a hero image that persists between routes without re-painting will not appear as an LCP candidate. INP can run lower because the JavaScript machinery is already in memory, and CLS may improve if content that would reflow on a full load stays put on a soft navigation. Timing baselines differ as well—soft navigations are measured from interaction start, full page loads from after navigation processing.

The cache advantage of MPAs

Nothing about the SPA architecture inherently blocks fast loads. A well-optimized SPA page can hit the same Core Web Vitals thresholds as its MPA counterpart. The real difference appears in the distribution of measured visits, not in the ceiling of performance.

MPAs treat every page as a fresh navigation, which means users tend to fetch multiple documents from the origin over a session. A larger share of that traffic benefits from warm caches. Core Web Vitals evaluates the 75th percentile of visits, so a site whose bundle of page loads skews heavily toward cached, fast navigations is more likely to land under the recommended thresholds. For MPAs to realize that edge, two conditions must hold: sub-resource caching has to be tuned well enough that same-origin loads are genuinely faster at the 75th percentile, and users must actually visit multiple pages to build that warm cache in the first place.

The comparison hinges on how data is aggregated. Scores grouped by origin let fast individual pages lift the 75th percentile site-wide. Scores grouped by page URL do not: an excellent cached start on a checkout page will not mask a slow landing page. PageSpeed Insights and the CrUX API both report metrics at the per-page and per-origin level, so the aggregation choice is visible and worth checking.

SPAs also carry a structural penalty where metrics extend across a page's lifespan. Users often stay on one "page" for the whole session, so any metric that accumulates over time weighs against the SPA.

Rethinking what the metrics reward

The historical gap in post-load performance measurement is a matter of effort and complexity. Post-load interactions are far more varied than the page load itself, making them a tougher target for metric design. The industry, Google included, has simply invested less there. That gap is closing with the soft-navigation APIs—but the load experience still needs to hold its place among incentives.

Google's stated goal with Web Vitals is to reward good experiences across the full span of loading and using a page. Metric design has steered clear of allowing fast post-load transitions to excuse poor initial loads, since users expect both.

Sites migrating from an MPA to an SPA will often see metric regressions, and that can be entirely down to a loss of warm-cache traffic, not a concrete performance problem. A direct comparison is available: run Lighthouse against both versions of the same landing page. A lower Core Web Vitals score on the SPA build points to a real load regression rather than a measurement artifact.

That said, switching back to an MPA purely to satisfy the metrics misses the point. The measurement gap was the problem—not the SPA architecture. Teams unhappy with their framework, or with a solid reason to believe an MPA will render a better user experience in practice, can justify the move. Chase better performance rather than better-looking numbers.

Debugging beyond the landing page

Field data for Core Web Vitals in Google tools like Search Console and PageSpeed Insights flows from CrUX, which aggregates by load URL only. SPA routes beyond the initial navigation have historically been invisible in those reports. CrUX integration for SPA routes is in progress, but site owners can begin using the new APIs now to measure Core Web Vitals per route and get a preview of how their scores will shift.

A path toward fair comparison

The unfairness between architectures is not inherent to SPAs—it is a measurement artifact. Core Web Vitals aggregates all visits into one bucket: cold starts and cache hits share the same distribution. With the soft navigation work, Google says there should no longer be a fundamental disadvantage to SPAs, assuming tooling parity eventually arrives.

Normalization efforts could go further. Separating cross-origin from same-origin visit data is one candidate approach. Treating those visits in distinct buckets, potentially even under distinct threshold recommendations, would reward good cache behavior without letting fast intra-site hops hide a slow landing page. It would also remove any incentive to fragment pages purely to inflate scores. Both experiences would remain important, and relative traffic shares on a given site would not so easily distort the metrics.

Closing the soft navigation gap

Soft navigation support is arguably the most significant recent addition to Core Web Vitals. It fills an acknowledged blind spot where SPA route changes — often the primary user experience — were previously outside the metrics' scope. The APIs introduced to address this (most notably InteractionContentfulPaint) now capture the rendering performance of these transitions.

Beyond closing the measurement hole, Google sees a broader future for the "soft" navigation APIs. With their original goal achieved, the expectation is that these primitives will unlock further use cases and optimizations for developers working with SPA architectures.

These improvements mark a step toward a more accurate picture of real-world performance for modern sites, and an invitation for continued community input as the metrics evolve. Feedback on the current or future Web Vitals metrics remains a critical channel; the door for that conversation is open via [email protected].