Diagnosing INP Regressions via the LoAF API
Long Animation Frames API entries expose script attribution, style/layout cost and presentation delay hidden by the Long Tasks API's flat 50ms bucket.

In this guide
Table of Contents
Table of contents
A p75 Interaction to Next Paint (INP) score of 340ms with a Long Tasks API report showing nothing over 60ms is not a contradiction — it is a measurement gap. The Long Tasks API flags any main-thread block exceeding 50ms, but it treats the entire task as an opaque scripting blob. It cannot tell you whether the delay came from a third-party analytics script, a synchronous layout recalculation triggered by a CSS-in-JS library, or presentation delay waiting on the compositor. When you’re chasing INP regressions in a production SPA, that opacity is the bottleneck. The Long Animation Frames API (LoAF) exists specifically to close this attribution gap by decomposing a slow frame into its constituent phases: script execution, style/layout work, and render delay.
This article covers the architecture of LoAF entries, how to wire a PerformanceObserver pipeline that correlates them with real user interactions, and how to enforce frame-budget gates in CI before a regression reaches production RUM dashboards.
#Why the Long Tasks API Under-Reports INP Cost
INP measures the latency between a user interaction (click, keypress, tap) and the next paint that visually reflects the result. That latency spans four phases: input delay (main thread busy when the event fires), processing time (event handler execution), presentation delay (style recalculation, layout, paint, compositing, and the wait for the next vsync). The Long Tasks API only observes the second phase reliably. Presentation delay — frequently the largest contributor on layout-heavy dashboards — is invisible to it entirely.
The Long Animation Frames API specification addresses this by emitting a single PerformanceLongAnimationFrameTiming entry per slow frame, with a nested scripts array attributing duration to individual invokers (event handlers, promise resolutions, requestAnimationFrame callbacks) and explicit styleAndLayoutStart / renderStart timestamps. This turns a single flat 50ms number into a phase-resolved trace you can act on.
#Architectural Breakdown of a LoAF Entry
Each frame the browser renders passes through a defined pipeline: input handling, JavaScript execution (including microtasks and rAF callbacks), style recalculation, layout, paint, and compositing, followed by presentation to the screen. A LoAF entry is only generated when total frame duration exceeds the 50ms threshold, mirroring the Long Tasks API cutoff, but unlike Long Tasks it captures the full pipeline rather than just the scripting segment.
Rendering diagram...
Run the trace five times minimum per route and take the median rather than a single pass; frame timing on CI runners is noisy due to shared CPU contention, and a single-run gate produces flaky failures that erode trust in the check.
#Failure Modes and Edge Cases
The Long Animation Frames API has real limitations that will bite you in production if unaccounted for.
Cross-origin script attribution collapses. If the dominant script in a slow frame originates from a third-party origin without the Timing-Allow-Origin header, sourceURL and sourceFunctionName return empty strings. You’ll see the frame but not the culprit — a common scenario with ad tech, chat widgets, and analytics SDKs.

Buffer eviction under high-frequency interaction. The performance entry buffer has a bounded size (typically 200 entries pre-observer-registration). On interaction-heavy SPAs — infinite-scroll feeds, drag-and-drop builders — early frames get evicted before your observer flushes, silently truncating attribution data. Register the observer as early as possible in the document head, before hydration begins.
Browser support asymmetry. LoAF is Chromium-only as of current shipping versions. Firefox and Safari fall back to the Long Tasks API or nothing. Any INP diagnostics dashboard built on LoAF needs a feature-detection fallback path, otherwise your Safari traffic silently disappears from attribution reports rather than reporting degraded data.
rAF callback misattribution. Animation-driven UI libraries schedule work inside requestAnimationFrame, which LoAF attributes to the frame it executes in, not the frame that scheduled it. If your interaction handler defers heavy work via rAF to “avoid blocking,” the LoAF trace will still show it as the dominant script — deferral doesn’t remove the cost, it just moves the attribution window.
#Diagnostic Comparison Table
| API | Capture Scope | Threshold | Attribution Granularity | Best Use Case |
|---|---|---|---|---|
| Long Tasks API | Script execution only | 50ms | None (opaque task) | Coarse main-thread blocking alerts |
| Long Animation Frames API | Full pipeline: script, style, layout, render | 50ms | Per-script invoker, source, function | Root-causing INP regressions |
| Event Timing API | Interaction lifecycle | None (all interactions) | Input delay, processing, presentation delay totals | Computing INP score itself |
| Layout Instability API | Unexpected layout shifts | None | Affected DOM nodes | CLS diagnostics, not INP |
#Scaling and Security Trade-offs
Deploying LoAF-based attribution at fleet scale introduces cost and privacy considerations that need explicit sign-off from your platform and security teams before rollout.
- RUM ingestion volume — on high-traffic routes, batching every LoAF entry into your analytics pipeline can multiply event volume 3–5x versus Web Vitals alone; sample at 10–20% for high-cardinality routes and retain 100% only for checkout/critical-path flows.
- Source attribution as a data leak vector —
sourceFunctionNameand stack-adjacent fields can expose internal code structure or third-party vendor names in client-side network requests; strip or hash these fields before they leave the browser if your CSP or data governance policy restricts vendor disclosure. - Sampling bias on low-end devices — devices already struggling with main-thread contention generate disproportionately more LoAF entries, skewing your p75 upward if your sampling isn’t device-class stratified; segment aggregation by device memory/CPU tier rather than a flat global percentile.
- CI trace noise vs production fidelity — synthetic Puppeteer traces on shared CI runners rarely match real device thermal and CPU throttling behaviour, so a budget that passes in CI can still regress in the field; treat CI gating as a regression tripwire, not a substitute for RUM validation post-deploy.
Treat LoAF as the attribution layer that sits underneath your INP score rather than a replacement metric. The score tells stakeholders whether the experience is acceptable; the LoAF trace tells your engineering team exactly which invoker, source file, and pipeline phase to fix. Wiring both into the same dashboard, with CI gating catching regressions before they reach field measurement, closes the loop between synthetic testing and real-user telemetry that most performance monitoring stacks currently leave disconnected.
Evidence trail
Sources and verification
Primary documentation and external technical references used in this article.
Related Engineering Labs
Related articles
Software Architecture
Software Architecture Reliability Checks with API
Implement bounded API reliability checks with observable success criteria and safe recovery paths.
Software Architecture
Circuit-Breaker Isolation Boundaries for a Bounded API Software Architecture Workflow
How to add a circuit-breaker and bulkhead isolation boundary around one API dependency, with staged shadow-to-enforcing rollout, explicit validation and a prepared rollback path.
Software Architecture
Rolling Out a New API Version Without Breaking Existing Consumers
A bounded, evidence-led method for rolling out a new API version behind an existing gateway using weighted traffic splitting, explicit validation gates and a rehearsed rollback path.
Software Architecture
Running a 5% API Canary with Health Gates
A bounded, evidence-led workflow for routing a small percentage of API traffic to a new deployment, validating it against explicit thresholds, and rolling it back deterministically if it fails.
Learn More About KBY
About KBY
Learn about our mission, editorial standards, and commitment to trusted engineering knowledge.
Why Trust KBY
Explore the processes and policies that ensure our publications are accurate, useful, and responsible.
Newsletter
Get our latest editorial publications, research and practical insights sent directly to your inbox.
Was this useful?
Engineering insights, direct to you.
Receive the latest Systems Engineering tutorials, production guides, Engineering Labs and operational best practices.
Comments
Add a thoughtful note on Diagnosing INP Regressions via the LoAF API. Comments are checked for spam and held for moderation before appearing.