mobilecachingsegmentation

Mobile Web Performance: Cold Starts, Cached Views, and What Your p75 Hides

By Grace Yoon··7 min read
A cached second visit and a cold-start first visit behave like entirely different pages.

When a user opens your product page for the first time on a mid-range Android phone over 4G, they experience something categorically different from a returning user opening the same page from a browser that cached sub-resources three days ago. Both visits get counted in your p75 LCP. Both contribute to your Core Web Vitals score. But they are not the same event, and optimizing for one without understanding the other leads to performance work that looks good in aggregate while leaving one population fully unaddressed.

Most teams that track p75 LCP are running a single aggregate metric. Segment by cache state and device category, and that aggregate frequently splits into two numbers that require different fixes — and sometimes represent a 2–3x gap in load time.

What Cold Start Actually Means on Mobile

A cold start on mobile is worse than a cold start on desktop for reasons that compound. The obvious one is network: a first-time visitor on 4G has to fetch all critical resources from scratch — HTML, CSS, fonts, hero image, JavaScript bundles. No service worker, no disk cache, no memory cache. Every byte is a fresh network request.

The less obvious reasons have to do with mobile browser behavior under resource pressure. Mobile browsers, especially on mid-range devices with 3–4GB RAM, are aggressive about process management. A browser tab that was killed by the OS to free memory — and then reopened — behaves similarly to a cold start even if the device has technically "visited" the page before. Cache entries may be present on disk, but the browser process itself needs to be re-initialized, and disk cache reads on flash storage under memory pressure can be significantly slower than expected.

Additionally, mobile CPUs run at reduced clock speeds when thermally constrained. A device that has been active for an hour running a navigation app alongside your product page is not the same hardware as a device that just woke from sleep. JavaScript parsing and execution times measured on a fresh device in a lab will consistently underestimate the execution cost on a thermally throttled device in real use.

Cache States and Their Effect on LCP

Cache state for web performance purposes has several distinct layers, and each behaves differently:

Memory cache. In-process cache for the current browser session. Fastest. A resource fetched earlier in the same tab session may be served from memory cache with effectively zero network cost. LCP for a same-session revisit is dramatically faster than for a cross-session revisit.

Disk cache. Persisted across sessions. Resources with appropriate cache-control headers (max-age or s-maxage sufficient for the inter-session gap) are served from disk without a network request. LCP improvement from disk cache is significant on desktop; on mobile it can vary by 30–50% depending on storage speed and device age.

Service worker cache. Explicit developer-controlled cache layer. If your site uses a service worker with a precache strategy for critical assets, returning users may get near-instant sub-resource responses regardless of disk cache state. Service worker cache survives across browser sessions and even some OS-level cache clearing events. It is the most reliable caching mechanism for controlled offline-first or fast-repeat-visit scenarios.

No cache (cold start). All resources fetched from origin or CDN edge. Full network cost, full JavaScript parse and execution cost. On mobile 4G, this is the scenario where your longest p75 LCP times come from.

A single p75 LCP number averages across all of these. Your returning users on WiFi with memory or disk cache are pulling your p75 down. Your new users on 4G cold start are pushing it up. The two populations are mixed in a single number.

Segmenting by Cache State and Visit Type

The practical way to segment by cache state in real-user data is to use a combination of navigation type (the Navigation Timing API's type field distinguishes reload, back-forward, and new navigation) and a custom first-visit indicator stored in a session or local storage entry.

A navigation type of navigate with no first-visit flag in storage is a reliable proxy for a cold start. A navigation type of navigate with a first-visit flag already present indicates a returning user on a new navigation. A back-forward navigation type indicates a bfcache-eligible page load, which has very different LCP characteristics — bfcache restores from a frozen snapshot, so LCP fires essentially instantly and the metric becomes less meaningful as a load performance indicator.

Consider a SaaS onboarding flow where a mid-sized engineering team instrument their field data with visit type segmentation for the first time. Their aggregate mobile p75 LCP was 3.6 seconds — in the "needs improvement" band. When segmented, cold-start first visits on mobile showed a p75 of 5.8 seconds. Returning mobile visits with warm cache showed 1.9 seconds. The aggregate looked like a "needs improvement" situation. The cold-start situation was actually a significant user experience problem — and the returning-visit situation was already comfortably in "good" territory.

The optimization priority reversed immediately. The work needed was not on returning-user performance (already fast) but exclusively on cold-start resource loading: hero image preload hints, font-display swap to avoid FOIT, deferred third-party script initialization, and a service worker with stale-while-revalidate caching for critical CSS and JS bundles.

Device Class as a Required Second Dimension

Cache state segmentation alone is not sufficient. Device class interacts with cache state in ways that matter for prioritization. A cold start on a high-end iPhone on 5G is categorically different from a cold start on a mid-range Android on 4G. The iPhone will fetch resources fast and parse JavaScript fast. The Android will face slower network AND slower JS execution.

The device class dimension can be approximated from user agent strings (though with accuracy limits after UA reduction), from navigator hardware concurrency and memory APIs, or from device category heuristics based on known device model strings. The coarse segmentation of "high-end device" vs. "low-to-mid-range device" is sufficient for most optimization decisions: if your low-end mobile cold start p75 is your worst metric, your optimization strategy should prioritize reducing JavaScript parse cost and image payload, not micro-optimizing font loading on desktop.

What bfcache Changes About Your Metrics

Back-forward cache (bfcache) is worth special attention because it fundamentally changes the meaning of LCP. When a browser restores a page from bfcache, the page is rendered from a frozen snapshot — no network requests, no JavaScript initialization, no layout. LCP fires almost immediately from a wall-clock perspective, but the "LCP time" captured by the PerformanceObserver is the time since navigation start, which for a bfcache restore can be sub-100ms.

We are not saying bfcache LCP values should be excluded from all reporting. They are real events that affect the aggregate. But they should be segmented separately from full-page navigations when you are making optimization decisions, because bfcache LCP is not something you can engineer — it depends on the browser's ability to hold a page in memory and restore it, which is outside your control beyond ensuring your page does not disqualify itself from bfcache eligibility (by using unload handlers or keeping open service worker connections that block freezing).

The Practical Monitoring Approach

A p75 LCP tracking setup that treats mobile performance seriously needs at minimum these segments emitted alongside every LCP observation: navigation type, first-visit flag, device category (coarse), and connection type. With those four dimensions, you can answer the questions that actually matter: how slow is my cold start on mid-range mobile on 4G, and is it getting better or worse after each deploy?

The aggregate p75 is still a useful headline metric for tracking overall trend. But when it moves — up or down — you need the segmented breakdown to understand why, and which user population drove the change. A headline p75 improvement that came entirely from faster returning-user cache behavior does not mean cold-start new visitors are in better shape. The segments tell you.

← All articles

See the real numbers behind your pages.

Free tier. No credit card.