Early publish, still editing and receiving feedback.
LCP measured on soft-navigations is slightly faster on 31 of 44 well-known Swedish sites. The typical change is small, but some sites see massive changes: Blocket’s LCP goes from 1.2s to 0.5s and SJ’s drops from 4.2s to 1.4s … why?
The moment is here!
Today everything changed for the better, and we will start to be able to get answers (or at least glean some insights) for the questions that have been asked since the dawn of Single Page Applications: Are Single Page Applications (SPAs) or Multi-Page Applications (MPAs) best for users?
So… what changed today, why is Gustav excited?
Chrome has been rolling out CWV for “soft-navigations” in the past few Chrome versions.
This in itself is not really dynamite stuff.
The dynamite stuff is that the latest Chrome UX Report has a super juicy update: real user performance metrics for soft navigations across sites globally.
This means we can start to find an answer to “is SPA or MPA good for my users?”
The SPA vs. MPA debate
I’ve been building websites since roughly around the time of the millennium bug.
For the past 12 years or so, I’ve been a participant and spectator in the long running debate of “SPA” vs “MPA”. Often the debate feels kind of like emacs vs. vim - one is obviously better (vim), but people are entrenched in their own beliefs colored by their own biases, experiences and just preferences without any real logic to it.
Disclaimer: I’m a strong proponent of multi page applications, unless there’s some strong benefit only an SPA will give your users. Picking SPA by default is a bit of an “ick”1 to me.
What I love about this new dataset is that it allows us to dig into specific markets.
The feedback I’ve gotten talking about performance over the years has been that “The internet is fast: We don’t need to care”. A statement I disagree with.
With that, let’s dig into the Swedish market where the average user has a high-end phone and 5G connectivity. Everything should be fast now and SPAs in particular would shine, right?
How soft navigations change LCP on Swedish sites
News
No surprises here
To me this is the least surprising chart to look at. Most news websites are not built using SPA / using soft navigations.
SPA sites like SVT, Omni, Corren and GP get small performance bumps here and Omni becomes the fastest Swedish news website.
Second hand sites
Did Blocket navigations really get 2x faster with soft navigations?
From what I can tell, Blocket, while built on “SPA tech (ReactJS/Next.js)” is doing server side rendering and hard navigations.
The reason for the soft navigations’ incredible speed seems to stem from the fact that browsing the galleries on the classifieds listings is classified as “soft navigations” … and yeah - it makes sense that browsing a gallery is hopefully a lot faster than loading a full page. Are such navigations “navigations” in the true sense though? The jury is still out on the definitions here, I believe.
Real estate
Hemnet goes from fastest to slowest
On hard navigations Hemnet is the fastest real estate site at 1.35s. With soft navigations it’s the slowest one at 1.44s - the other three all get faster while Hemnet gets slower.
Travel
SJ.se gets a performance improvement from 4.2s to 1.4s
This is massive, and from my testing appears to be accurate and correct. Full page loads on SJ are painfully slow, but much of the end user use case comes down to booking tickets, navigating within the SPA app itself and the data seems to back this up: Real users are only suffering on the full page load but the overall experience is “ok”.
More categories of sites
Show Retail, Banking and Public services
Retail
Banking
Public services
My conclusion
It’s still a bit too early to tell what to make of this data.
With an SPA site, users typically pay a performance penalty up front (heavy JS bundle) for the idea that future navigations will be much faster. It’s still early days with this data, but so far I don’t really see this paying off for most sites.
Yes, Swedish SPA sites get a better UX measurement with the softnavs.
No, they’re not blazingly fast - they’re equal to MPAs.
I will probably do an update here later with more data. If you want to give feedback on this blog post feel free to reach out.
About the data
Data was pulled from CrUX 2 September 2026 on BigQuery 3.
The dataset was limited to “country_se” as that’s what I wanted to look at. If you want to run this yourself for other countries, verify my findings or look at domains I skipped, you can use the query below.
Show the query
CREATE TEMP FUNCTION GET_PERCENTILE(
bins ANY TYPE,
target_percentile FLOAT64
) RETURNS FLOAT64 AS ((
WITH raw_bins AS (
SELECT
bin.start AS bin_start,
bin.end AS bin_end,
bin.density AS bin_density
FROM UNNEST(bins) AS bin
),
normalized_bins AS (
SELECT
*,
SAFE_DIVIDE(
bin_density,
SUM(bin_density) OVER ()
) AS density
FROM raw_bins
),
ranked_bins AS (
SELECT
*,
SUM(density) OVER (
ORDER BY bin_start
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
) AS cum_density
FROM normalized_bins
),
target_bin AS (
SELECT
*,
LAG(cum_density, 1, 0.0) OVER (
ORDER BY bin_start
) AS prev_cum_density
FROM ranked_bins
)
SELECT
(
SELECT
CASE
WHEN density IS NULL OR density <= 0 THEN NULL
WHEN bin_end IS NULL THEN NULL
ELSE bin_start
+ (bin_end - bin_start)
* SAFE_DIVIDE(
target_percentile - prev_cum_density,
density
)
END
FROM target_bin
WHERE cum_density >= target_percentile
ORDER BY bin_start
LIMIT 1
)
));
SELECT
origin,
form_factor.name AS form_factor,
-- Standard LCP Percentiles
GET_PERCENTILE(largest_contentful_paint.histogram.bin, 0.25) AS lcp_p25,
GET_PERCENTILE(largest_contentful_paint.histogram.bin, 0.50) AS lcp_p50,
GET_PERCENTILE(largest_contentful_paint.histogram.bin, 0.75) AS lcp_p75,
GET_PERCENTILE(largest_contentful_paint.histogram.bin, 0.95) AS lcp_p95,
GET_PERCENTILE(largest_contentful_paint.histogram.bin, 0.99) AS lcp_p99,
-- Soft Nav LCP Percentiles
GET_PERCENTILE(experimental.largest_contentful_paint_with_softnavs.histogram.bin, 0.25) AS softnav_lcp_p25,
GET_PERCENTILE(experimental.largest_contentful_paint_with_softnavs.histogram.bin, 0.50) AS softnav_lcp_p50,
GET_PERCENTILE(experimental.largest_contentful_paint_with_softnavs.histogram.bin, 0.75) AS softnav_lcp_p75,
GET_PERCENTILE(experimental.largest_contentful_paint_with_softnavs.histogram.bin, 0.95) AS softnav_lcp_p95,
GET_PERCENTILE(experimental.largest_contentful_paint_with_softnavs.histogram.bin, 0.99) AS softnav_lcp_p99
FROM
`chrome-ux-report.country_se.202609`
WHERE
experimental.popularity.rank <= 1000
Show the data for all 44 sites
| Domain | Hard p75 | Soft p75 | Change |
|---|---|---|---|
| blocket.se | 1.2s | 0.53s | -54% |
| inet.se | 0.68s | 0.65s | -4.4% |
| polisen.se | 0.78s | 0.71s | -8.6% |
| omni.se | 1.2s | 0.82s | -33% |
| aftonbladet.se | 0.87s | 0.82s | -5.5% |
| arbetsformedlingen.se | 1.6s | 0.87s | -45% |
| forsakringskassan.se | 0.92s | 0.88s | -5.1% |
| apotea.se | 0.95s | 0.94s | -0.42% |
| seb.se | 0.97s | 0.96s | -1.3% |
| corren.se | 1.3s | 0.98s | -22% |
| webhallen.com | 1.6s | 1.1s | -33% |
| qasa.com | 2.4s | 1.1s | -56% |
| svt.se | 1.5s | 1.1s | -31% |
| sverigesradio.se | 1.2s | 1.1s | -5.9% |
| systembolaget.se | 1.6s | 1.1s | -27% |
| svd.se | 1.2s | 1.2s | -0.86% |
| skatteverket.se | 1.2s | 1.2s | -0.34% |
| amazon.se | 1.2s | 1.2s | -0.83% |
| 1177.se | 1.2s | 1.2s | -0.17% |
| dn.se | 1.3s | 1.3s | -0.68% |
| booli.se | 1.9s | 1.3s | -30% |
| tradera.com | 1.6s | 1.3s | -17% |
| zalando.se | 1.2s | 1.4s | 9.8% |
| sydsvenskan.se | 1.4s | 1.4s | -0.22% |
| sas.se | 1.8s | 1.4s | -24% |
| homeq.se | 2s | 1.4s | -32% |
| vasttrafik.se | 1.4s | 1.4s | -0.36% |
| gp.se | 1.6s | 1.4s | -13% |
| expressen.se | 1.4s | 1.4s | 0% |
| handelsbanken.se | 1.5s | 1.4s | -8.2% |
| sj.se | 4.2s | 1.4s | -66% |
| hemnet.se | 1.3s | 1.4s | 6.8% |
| ica.se | 1.5s | 1.5s | -3.5% |
| avanza.se | 2.2s | 1.5s | -34% |
| sellpy.se | 2.4s | 1.5s | -36% |
| elgiganten.se | 1.6s | 1.5s | -3.5% |
| cdon.se | 1.7s | 1.6s | -9% |
| swedbank.se | 1.7s | 1.7s | -0.64% |
| sl.se | 2.1s | 1.7s | -16% |
| nordea.se | 1.9s | 1.8s | -3% |
| vinted.se | 2s | 1.9s | -3.8% |
| di.se | 2.1s | 2.1s | -0.19% |
| skanetrafiken.se | 2.3s | 2.2s | -5.6% |
| nordnet.se | 3.8s | 2.3s | -39% |
This is apparently Cool Kid slang nowadays, I’m a cool kid. ↩︎
One obvious limitation is that the CrUX dataset is only Chrome users. Imagine if Safari would tell us what goes on in Safariland - that would be a nice thing, wouldn’t it? ↩︎
I ran the BigQuery queries with my personal Google Cloud account within the free tier - no employer money or time wasted on this deep dive :) ↩︎