You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Studio has not reported a single LCP or FCP measurement in over three weeks. Coverage of initial_load views collapsed from ~55% to exactly 0% around 2026-07-04 and has stayed there.
This means #1405 (open — "LCP performance regression: '/' view degraded +61.7%, 4320ms p75") can no longer be measured, confirmed, or closed, and no future LCP/FCP regression can be detected at all.
Surfaced by the automated daily RUM review (app f590deee-…).
Datadog findings
Coverage = share of @type:view @view.loading_type:initial_load events carrying the metric:
Metric
~2026-06-26 → 06-30
~2026-07-04 → 07-06
last 24h
@view.largest_contentful_paint
85/156 = 54.5%
0/61 = 0.0%
0/160 = 0.0%
@view.first_contentful_paint
89/156 = 57.1%
0/61 = 0.0%
0/160 = 0.0%
@view.dom_complete
98/156 = 62.8%
5/61 = 8.2%
39/160 = 24.4%
@view.loading_time
0/156 = 0.0%
0/61 = 0.0%
0/160 = 0.0%
@view.first_input_delay and @view.interaction_to_next_paint also return no data.
The signature is precise
dom_complete still works. LCP and FCP are exactly zero.
dom_complete comes from PerformanceNavigationTiming; LCP and FCP come from PerformanceObserver entries. Views are still being created and still carry navigation timings — so this is not a sampling, ingestion, or view-tracking outage. Specifically the paint-observer metrics stopped reaching the view.
A "0 out of 160" is not sparsity: at the old ~55% rate we'd expect ~88.
Narrowing the break
Two-day buckets put the transition between ~2026-07-02→07-04 (39.8% coverage) and ~2026-07-04→07-06 (0.0%):
window (rel. to 2026-07-28)
initial loads
with LCP
pct
32d → 28d
156
85
54.5%
28d → 26d
287
152
53.0%
26d → 24d
98
39
39.8%
24d → 22d
60
0
0.0%
22d → 20d
298
6
2.0%
18d → 16d
112
1
0.9%
14d → 12d
263
6
2.3%
8d → 6d
252
3
1.2%
(The residual 1–2% after the break is a handful of stragglers, presumably long-lived tabs on older bundles.)
Not the SDK.@datadog/browser-rum resolved to 7.4.0 on both sides of that boundary (7.2.0 Jun 19 → 7.3.0 Jun 22 → 7.4.0 Jun 29 → 7.5.0 Jul 13 → 7.6.1 Jul 27). Prod is currently on sdk_version:7.5.0. The break predates the 7.5.0 bump by ~10 days.
Likely mechanism
src/integrations/datadog/datadog.ts initializes with trackViewsManually: true, then starts a view twice during startup:
useDatadog (called from src/App.tsx) inits RUM inside a useEffect — i.e. after React mounts — and on onReady calls startView({ name: window.location.pathname || 'initial' }).
useOnRouteLoadTracker (called from src/components/StudioCloud.tsx) then calls startView again with the translated route name, on an effect keyed [location.href, router].
With trackViewsManually, Datadog attributes LCP/FCP to the initial view, and stops collecting once that view ends. If the second startView replaces the initial view before the browser settles the largest paint, both metrics are dropped — which matches the data exactly (paint observers zeroed, navigation timings unaffected).
Two commits in the bisect window plausibly changed that startup timing:
4f660718 (2026-07-03) fix(router): create the TanStack router once, not on every AppRouted render — the closest date match, and it directly changes the router identity that useOnRouteLoadTracker's effect is keyed on, hence when the second startView fires. (Context in CLAUDE.md under "the router must be created exactly once".)
7c5e9141 (2026-07-06) fix(auth): subscribe useRootAuthenticationContext once, not per change — also changes render/effect cadence around startup.
I want to be clear this is a hypothesis, not a proven cause — the correlation is by date and mechanism, and I could not reproduce paint-metric collection locally (it needs a production build and real page loads).
Suggested next steps
Confirm the mechanism with a production-mode build: init RUM, log datadogRum.getInternalContext() view ids across the two startView calls, and check whether the initial view ends before LCP settles.
Don't replace the initial view. Either drop the startView in useDatadog and let useOnRouteLoadTracker name the first view, or keep the initial view and only startView on subsequent route changes. One view per page load at startup, not two.
Consider initializing RUM outside a useEffect — at module scope in the entry, before React mounts — so the SDK's observers attach as early as possible.
Re-evaluate trackViewsManually: true. If it's only there for the friendly route names, @datadog/browser-rum-react's router instrumentation may give both naming and correct vitals.
Add a guard against silent loss: a Datadog monitor on LCP sample count per day would have caught this three weeks ago. Right now nothing alerts when a metric simply stops arriving.
Summary
Studio has not reported a single LCP or FCP measurement in over three weeks. Coverage of
initial_loadviews collapsed from ~55% to exactly 0% around 2026-07-04 and has stayed there.This means #1405 (open — "LCP performance regression: '/' view degraded +61.7%, 4320ms p75") can no longer be measured, confirmed, or closed, and no future LCP/FCP regression can be detected at all.
Surfaced by the automated daily RUM review (app
f590deee-…).Datadog findings
Coverage = share of
@type:view @view.loading_type:initial_loadevents carrying the metric:@view.largest_contentful_paint@view.first_contentful_paint@view.dom_complete@view.loading_time@view.first_input_delayand@view.interaction_to_next_paintalso return no data.The signature is precise
dom_completestill works. LCP and FCP are exactly zero.dom_completecomes fromPerformanceNavigationTiming; LCP and FCP come fromPerformanceObserverentries. Views are still being created and still carry navigation timings — so this is not a sampling, ingestion, or view-tracking outage. Specifically the paint-observer metrics stopped reaching the view.A "0 out of 160" is not sparsity: at the old ~55% rate we'd expect ~88.
Narrowing the break
Two-day buckets put the transition between ~2026-07-02→07-04 (39.8% coverage) and ~2026-07-04→07-06 (0.0%):
(The residual 1–2% after the break is a handful of stragglers, presumably long-lived tabs on older bundles.)
Not the SDK.
@datadog/browser-rumresolved to 7.4.0 on both sides of that boundary (7.2.0 Jun 19 → 7.3.0 Jun 22 → 7.4.0 Jun 29 → 7.5.0 Jul 13 → 7.6.1 Jul 27). Prod is currently onsdk_version:7.5.0. The break predates the 7.5.0 bump by ~10 days.Likely mechanism
src/integrations/datadog/datadog.tsinitializes withtrackViewsManually: true, then starts a view twice during startup:useDatadog(called fromsrc/App.tsx) inits RUM inside auseEffect— i.e. after React mounts — and ononReadycallsstartView({ name: window.location.pathname || 'initial' }).useOnRouteLoadTracker(called fromsrc/components/StudioCloud.tsx) then callsstartViewagain with the translated route name, on an effect keyed[location.href, router].With
trackViewsManually, Datadog attributes LCP/FCP to the initial view, and stops collecting once that view ends. If the secondstartViewreplaces the initial view before the browser settles the largest paint, both metrics are dropped — which matches the data exactly (paint observers zeroed, navigation timings unaffected).Two commits in the bisect window plausibly changed that startup timing:
4f660718(2026-07-03)fix(router): create the TanStack router once, not on every AppRouted render— the closest date match, and it directly changes therouteridentity thatuseOnRouteLoadTracker's effect is keyed on, hence when the secondstartViewfires. (Context inCLAUDE.mdunder "the router must be created exactly once".)7c5e9141(2026-07-06)fix(auth): subscribe useRootAuthenticationContext once, not per change— also changes render/effect cadence around startup.I want to be clear this is a hypothesis, not a proven cause — the correlation is by date and mechanism, and I could not reproduce paint-metric collection locally (it needs a production build and real page loads).
Suggested next steps
datadogRum.getInternalContext()view ids across the twostartViewcalls, and check whether the initial view ends before LCP settles.startViewinuseDatadogand letuseOnRouteLoadTrackername the first view, or keep the initial view and onlystartViewon subsequent route changes. One view per page load at startup, not two.useEffect— at module scope in the entry, before React mounts — so the SDK's observers attach as early as possible.trackViewsManually: true. If it's only there for the friendly route names,@datadog/browser-rum-react's router instrumentation may give both naming and correct vitals.Related
Filed by the automated daily Datadog RUM review. No PII or customer identifiers included.