Flare by Spatie
    • Error Tracking
    • Performance Monitoring
    • Logs
  • Pricing
  • Docs
  • Insights
  • Changelog
  • Back to Flare ⌘↵ Shortcut: Command or Control Enter
  • Sign in
  • Try Flare for free
  • Error Tracking
  • Performance Monitoring
  • Logs
  • Pricing
  • Docs
  • Insights
  • Changelog
    • Back to Flare ⌘↵ Shortcut: Command or Control Enter
    • Try Flare for free
    • Sign in
Flare Flare PHP PHP JavaScript JavaScript Protocol Protocol
  • General
  • Welcome to Flare
  • Getting started
  • Our MCP server
  • Agent skill
  • Using the CLI
  • Using the API
  • Errors
  • Working with errors
  • Searching errors
  • Sharing errors
  • Error grouping
  • Spike protection
  • Logs
  • Working with logs
  • Performance
  • How it works
  • Dashboard
  • Summary view
  • Aggregate view
  • Working with traces
  • Web vitals
  • Integrations
  • GitHub
  • Jira
  • GitLab
  • Linear
  • Notifications
  • Configuring notifications
  • Mail
  • Slack
  • Telegram
  • SMS
  • Discord
  • Microsoft Teams
  • Webhooks

Web vitals

View as Markdown

Core Web Vitals are five numbers the browser measures about a page load. Flare collects them from your JavaScript projects and shows them in three places: on the Pages table, where you compare pages against each other, on the Performance dashboard, where you get one number for the whole site, and in the trace viewer, where you look at a single visit.

Only browser projects produce these numbers. See web vitals in the JavaScript SDK for how they get collected.

The five vitals

Vital Name What it measures
TTFB Time to first byte How long it took before the server started answering
FCP First contentful paint When the first text or image showed up
LCP Largest contentful paint When the biggest element on screen finished painting
INP Interaction to next paint The slowest reaction to a click, tap, or key press during the visit
CLS Cumulative layout shift How much the page moved around while it loaded

The first four are measured in milliseconds. CLS is a decimal without a unit.

On the Pages table

The Pages table gains four columns: a score, and then LCP, INP, and CLS.

The browser pages table in Flare showing the Score, LCP, INP and CLS columns

Every number in these columns is a p75 over the period you selected, not an average. So an LCP of 2.1 seconds means that 75 out of every 100 visits to that page painted their biggest element within 2.1 seconds, and the slowest 25 took longer. This is the number Google itself uses to judge a page, because an average hides your slowest visitors behind your fastest ones.

TTFB and FCP are missing from the table on purpose. They are still collected, and they still count towards the score, but LCP, INP, and CLS are the three Google calls Core Web Vitals, and a table with eight number columns is hard to read. You still see all five on a trace detail.

A column shows - when Flare has no measurement for that page. That usually means your visitors use a browser that can't measure it. CLS only works in Chromium browsers, so a page visited mostly from Safari shows - for CLS.

Thresholds

Each vital has two boundaries, taken from Google's published Core Web Vitals thresholds. Below the first one is good, above the second one is poor, and in between needs improvement. Flare colours every value green, yellow, or red on those boundaries.

Vital Good Needs improvement Poor
TTFB up to 800 ms 800 to 1800 ms over 1800 ms
FCP up to 1800 ms 1800 to 3000 ms over 3000 ms
LCP up to 2500 ms 2500 to 4000 ms over 4000 ms
INP up to 200 ms 200 to 500 ms over 500 ms
CLS up to 0.1 0.1 to 0.25 over 0.25

The score

The score puts all five vitals into one number between 0 and 100, so you can quickly spot which page needs your attention first without reading five columns.

Each vital is scored on its own first, using the boundaries in the table above. A value sitting exactly on the good boundary scores 90. A value sitting exactly on the poor boundary scores 50. The five scores are then weighted and added up:

Vital Weight
LCP 30%
INP 30%
CLS 15%
FCP 15%
TTFB 10%

LCP and INP carry the most weight because they describe what your visitor actually waits for. TTFB carries the least, because a fast server does not save a page that paints slowly.

The score is coloured the same way a single vital is: 90 and above is good, 50 to 89 needs improvement, below 50 is poor.

When the score is missing

When a vital was never measured, its weight is dropped and the remaining vitals are rescaled to fill the gap. A page with no CLS is scored on the other four.

Flare only shows a score when at least half of the total weight is present. Below that you get a - instead.

This rule exists because TTFB and FCP are the two that arrive earliest and most reliably, and they are usually green. Together they are a quarter of the weight. Scoring a page on those two alone would show a comfortable 95 while saying nothing about the parts your visitors feel most.

On the dashboard

The Performance dashboard opens with a "Browser pages" block. The two tiles at the top of that block show the web vitals of your whole site, over the period you picked in the top right corner.

The Browser pages block on the performance dashboard, with a web vitals performance score ring and a score breakdown chart above the response times and slow pages tiles

Both tiles merge every page load in that period and take the p75 per vital over all of them. They do not average the scores of your pages. So a page nobody visits does not pull the performance number down.

Performance score

The ring chart on the left holds the same score the Pages table shows per page, but now for the site as a whole. It should feel familiar to the one Lighthouse uses.

Every vital gets its own slice. The width of a slice is determined by the weight of its vital, so for example important metrics like LCP and INP each take up close to a third of the ring.

Missing vitals work the same as in the Pages table. A vital that was never measured shows - and the weight is spread over the others so the slices will adapt in their width. When less than half of the weight is present the ring shows --.

Score breakdown

The chart on the right is that same score, but over time. Each band is one vital, and the height of a band is what that vital contributed at that moment: its weight times its score. The bands stack up to the total score, which is why the axis stops at 100.

Hover the chart to read one moment: the total score, and what every vital contributed to it.

In the trace viewer

Open a single page load trace and you see the vitals for that one visit.

TTFB, FCP, and LCP appear as coloured chips on the page load bar, placed at the moment they happened. Each value is its own distance from the start of the page load, so the chip sits where the measurement landed on the timeline.

A trace waterfall with TTFB, FCP and LCP chips placed along the page load span bar

When a value falls past the right edge of the bar, its chip is pinned to the edge and marked with an arrow. An LCP that lands after the page load span closed still gets shown, rather than being pushed off screen.

INP and CLS get no chip. Neither of them describes a single moment: INP is one interaction somewhere in the visit and nothing records which one, and CLS adds up over the whole life of the page.

Select the page load span and the side panel shows a "Web vitals" section with all five, written out in full, with their unit and their colour.

The span side panel in Flare showing the Web vitals section with time to first byte, first contentful paint, largest contentful paint, interaction to next paint and cumulative layout shift

A vital the browser never measured is left out of this section rather than shown as zero. A CLS of 0 is a real result, so showing one for a browser that cannot measure CLS would read as a perfect page.

I'm missing some vitals?

If you open a trace right after a page load and you only see TTFB and FCP, that's normal. The other three are still being measured (LCP, CLS and INP).

The client sends them at the first client side route change, or when the visitor leaves, whichever comes first. Reload the trace after a few seconds and all five should be there.

The JS client sends them once and never updates them. On a normal site that means they cover the whole visit. In single page applications this only covers the initial pageload, so any navigation after that, does not record web vitals. This is by design, because clientside routing does not suffer from TTFB, FCP or LCP.

Where the numbers come from

Your visitors' browsers measure the vitals during a real visit, and the Flare JavaScript client sends them along with the page load trace. The values depend on the device, the connection, and the distance to your server, so they differ from what a testing tool reports on your own machine. You can compare the results to Google's Page Speed Index, but with a wider pool of devices.

Read web vitals in the JavaScript SDK for what the client does and which browser measures what.

Working with traces GitHub

On this page

  • The five vitals
  • On the Pages table
  • Thresholds
  • The score
  • On the dashboard
  • In the trace viewer
  • I'm missing some vitals?
  • Where the numbers come from

Catch errors and fix slowdowns with Flare, the full-stack application monitoring platform for Laravel, PHP & JavaScript.

  • Platform
  • Error Tracking
  • Performance Monitoring
  • Pricing
  • Support
  • Resources
  • Insights
  • Newsletter
  • Changelog
  • Documentation
  • Affiliate program
  • uptime status badge Service status
  • Terms of use
  • DPA
  • Privacy & cookie Policy
Made in by Spatie logo
Flare