Skip to content
Issue docs

Slow Speed Index

Suggestionslow_speed_indexIssue 179

What is this issue?

Speed Index measures how quickly the visible part of the page fills in during load. It is computed from a video of the page loading: a page that shows most of its content early scores better than one that stays blank and then appears all at once, even if both finish at the same moment.

Lighthouse scores it in three bands on mobile:

Speed Index Verdict
3.4 seconds or less Good
3.4 to 5.8 seconds Needs improvement
more than 5.8 seconds Slow

This suggestion is raised for pages past 5.8 seconds, measured in the PageSpeed lab run.

Why it matters

  • It is how fast the page feels. Two pages that finish loading at the same time can feel very different; Speed Index captures the one that shows something useful sooner.
  • It is part of the Lighthouse score PageSpeed Insights shows (10% of it).
  • It has no ranking weight of its own, which is why this is a suggestion rather than an issue. A slow Speed Index usually comes with a poor FCP or LCP, which do matter.

How to fix it

  1. Fix the first paint first. Everything that improves First Contentful Paint -- a faster server, fewer render-blocking resources, font-display -- improves Speed Index too.

  2. Render the visible content in the HTML. Content inserted by JavaScript after load appears late and all at once.

  3. Reserve space for late content so the page does not jump as it fills in, and lazy-load what is below the fold.

  4. Reduce main-thread work during load. Long tasks delay every frame of the paint (see "Total Blocking Time in the poor range").

Examples

1. Client-side rendering

A product page shipped an empty <div id="app"> and rendered everything from JavaScript after the bundle loaded.

Fails -- Speed Index 6.4 s: blank for five seconds, then everything at once.

Passes -- Speed Index 2.9 s: the same page server-rendered, with the scripts hydrating it afterwards.

2. A full-screen loading spinner

Fails -- Speed Index 6.0 s: a spinner covered the page until every image had loaded.

Passes -- Speed Index 3.1 s: the spinner removed; images load in place.

How PixyScan detects this

  1. Chooses which pages to measure. After the crawl, PixyScan measures the homepage plus the pages your own site links to most, up to a per-scan budget (ten pages by default, at most fifty). Measuring every page would take hours and exhaust the PageSpeed Insights quota of the API key it runs under.

  2. Asks the PageSpeed Insights API about each of them, on mobile. This needs the Hobby plan or above and a PageSpeed Insights API key on the site or its workspace.

  3. Reads Speed Index from the Lighthouse lab run (speed-index). There is no real-user Speed Index.

  4. Raises the suggestion only above 5.8 seconds -- the bound Lighthouse's mobile scoring calls slow. A page at exactly 5.8 seconds raises nothing.

  5. Raises nothing on a page it did not measure. A page outside the sample, and a page whose measurement failed, are both reported as Not measured. Neither is treated as passing, and neither can fail this check.

What we store

Storage Level

Page Level


Database Table / Prisma Model

PagePerformance (page_performance), with the finding itself on audit_issues.details.


Fields Used

Field Type Description
strategy String mobile or desktop. Every number in the row belongs to one form factor.
fetchedAt DateTime When PageSpeed answered. "Measured three weeks ago" is not "not measured".
errorReason String? Why a sampled page still has no numbers. Null when the call succeeded.
labSpeedIndexMs Int? Speed Index from the PageSpeed lab run (speed-index), in milliseconds.

On the finding (audit_issues.details): message, plus metric (speedIndex), source (lab), valueMs and thresholdMs (5800).


Detection Dependencies

  • PageSpeed Insights API v5 (lighthouseResult.audits), mobile strategy
  • The PageSpeed plan feature (Hobby and above) and a PageSpeed Insights API key
  • The crawl's internal link graph, which decides which pages are sampled

Note

A page with no row was never measured. The pass samples the homepage plus the most-linked pages within a per-scan budget (default 10, at most 50), so most pages of a site have no page_performance row at all. That is the normal state, it is drawn as Not measured, and this check cannot be raised against it.

A row whose metric columns are all null with an errorReason set is a different state again: the page WAS sampled and the measurement failed. It is still never reported as passing.

Further reading