INP statt FID — was die Core-Web-Vitals-Reform 2024 in der Praxis verändert hat
Seit dem 12. März 2024 misst Google nicht mehr die erste, sondern jede Interaktion. Zwei Jahre später ist klar — der Wechsel hat ein altes Problem freigelegt und zwingt Frontend-Teams zu echtem Performance-Engineering.
Am 12. März 2024 hat Google den First Input Delay (FID) aus den Core Web Vitals entfernt und durch Interaction to Next Paint (INP) ersetzt. Wer damals die Mailing-Liste der Chrome-Speed-Metrics gelesen hat, kennt das Datum als Fußnote. Wer 2026 ein Dashboard für Real-User-Monitoring betreut, kennt es als Wendepunkt — den Tag, an dem aus einer fast immer grünen Metrik eine fast immer gelbe wurde.
Zwei Jahre Bilanz, nüchtern.
Was sich gemessen ändert
FID hat eine einzige Zahl produziert: die Verzögerung zwischen dem ersten Tap, Klick oder Tastendruck einer Nutzerin und dem Moment, in dem der Browser begonnen hat, das zugehörige Event-Handling zu verarbeiten. Die Metrik war auf einen einzelnen Zeitpunkt beschränkt — den allerersten — und ignorierte alles, was danach kam.
INP misst grundsätzlich anders. Die Definition lautet:
Interaction to Next Paint ist die längste beobachtete Verzögerung zwischen einer Nutzer-Interaktion und dem nächsten Frame, der den Effekt dieser Interaktion zeigt — über die gesamte Lebensdauer einer Page, mit p98-Glättung gegen einzelne Ausreißer.
Drei Punkte daran sind entscheidend.
Erstens, INP misst nicht die erste Interaktion, sondern jede. Eine Page mit schnellem Initial-Tap, aber laggy Filter-Updates eine Minute später, fällt durch.
Zweitens, INP misst nicht den Beginn des Handlings, sondern den Effekt — den nächsten gerenderten Frame. Damit fließen Hydration-Cost, Reconciliation-Cost und Layout-Cost mit ein, nicht nur Event-Loop-Latenz.
Drittens, die Schwellen sind:
| Bereich | INP-Wert (75. Perzentil) |
|---|---|
| Gut | ≤ 200 ms |
| Verbesserungsbedürftig | 200–500 ms |
| Schlecht | > 500 ms |
Zum Vergleich: FID galt als „gut” bis 100 ms. Die INP-Schwelle ist absolut höher, aber sie misst über ein viel größeres Sample — und das ist die eigentliche Verschärfung.
Was die Statistik sagt
Die HTTP-Archive-Daten zum Stichtag März 2026 zeigen einen klaren Kontrast zur FID-Ära. Im Vor-INP-Zeitraum hatten etwa 95 % aller gemessenen Web-Pages einen FID im „guten” Bereich. Die Metrik war so durchgängig grün, dass sie als Performance-Signal kaum noch differenzierte.
INP zeigt ein anderes Bild. Die Verteilung Q1 2026:
- 62 % gut (≤ 200 ms)
- 23 % verbesserungsbedürftig (200–500 ms)
- 15 % schlecht (> 500 ms)
Anders gesagt: Etwa eine von vier Sites fällt jetzt durch das Performance-Audit, die unter dem alten Modell durchgekommen wäre. Das ist keine Verschlechterung der Sites — es ist eine Aufdeckung von Schwächen, die FID nie gemessen hat.
Besonders betroffen sind drei Site-Klassen:
- React/Next-basierte Marketing-Sites mit großen Hydration-Tasks (siehe das Schwester-Artikel zur Astro/Next-Architektur)
- E-Commerce-Filter-UIs, die bei jeder Checkbox-Änderung den ganzen Produktkatalog re-rendern
- Dashboards mit synchronen Updates auf große Datentabellen
Wo INP klemmt: drei Ursachen
In der Praxis lassen sich die meisten INP-Probleme auf eine von drei Klassen zurückführen.
1. Lange Tasks im Main Thread
Eine Aufgabe, die länger als 50 ms im Main Thread läuft, blockiert das Event-Handling für ihre Dauer. Das ist die klassische Ursache. Hauptverdächtige 2026:
- Hydration großer React-Komponentenbäume (Next, Remix, neuere CRA-Reste)
- Marketing-Tags (Google Tag Manager, Adobe Launch, kleinere Tracker-Pakete als Sammlung)
- State-Updates, die ganze Listen re-rendern, ohne Virtualisierung
2. Unoptimierte Event-Handler
Ein Click-Handler, der synchron 30.000 Items filtert, blockiert den Frame, in dem der Klick gerendert werden soll. Klassisches Beispiel:
// Anti-Pattern
function FilterBar() {
const [filter, setFilter] = useState('');
const filtered = useMemo(
() => products.filter((p) => p.name.includes(filter)),
[filter]
);
return (
<input
onChange={(e) => setFilter(e.target.value)}
// … each keystroke re-filters 30k products synchronously
/>
);
}
Das ist der Klassiker, der unter FID nie aufgefallen ist — der erste Tastendruck war schnell, alle weiteren wurden gemessen.
3. Synchrone Layouts nach Interaktion
Eine Komponente, die auf einen Klick hin den DOM mutiert, dann offsetWidth liest, dann erneut mutiert, erzwingt Layout-Thrashing innerhalb des Frames. Resultat: INP-Wert im Bereich von mehreren hundert Millisekunden, ohne dass im Code irgendetwas „langsam” aussieht.
Optimierungs-Strategien 2026
Vier Werkzeuge, die in der React/Web-Welt 2026 zur Routine geworden sind.
startTransition und useDeferredValue
React 18+ trennt explizit zwischen dringenden Updates (Input-Sync) und nicht-dringenden (Liste-Filtern). startTransition markiert ein Update als unterbrechbar:
import { useState, useTransition } from 'react';
function FilterBar({ products }) {
const [input, setInput] = useState('');
const [filtered, setFiltered] = useState(products);
const [isPending, startTransition] = useTransition();
function onChange(e) {
const value = e.target.value;
setInput(value); // sofort, hält das Input synchron
startTransition(() => {
setFiltered(products.filter((p) => p.name.includes(value)));
});
}
return (
<>
<input value={input} onChange={onChange} />
{isPending && <Spinner />}
<List items={filtered} />
</>
);
}
Der Input bleibt reaktiv, die teure Filter-Operation wird in eine unterbrechbare Transition verlagert. INP-Wert: in unseren Messungen typisch von 400–600 ms auf 80–120 ms.
useDeferredValue ist die deklarative Schwester für dieselbe Idee:
const deferredFilter = useDeferredValue(input);
const filtered = useMemo(
() => products.filter((p) => p.name.includes(deferredFilter)),
[deferredFilter, products]
);
scheduler.yield()
Für lange Tasks außerhalb von React — CSV-Parser, Excel-Export, Crypto-Operationen — bietet die Scheduler-API ab Chrome 129 die Möglichkeit, kooperativ an den Browser zurückzugeben:
async function parseLarge(rows) {
const results = [];
for (let i = 0; i < rows.length; i++) {
results.push(parseRow(rows[i]));
if (i % 100 === 0) {
await scheduler.yield();
}
}
return results;
}
scheduler.yield() gibt den Main Thread für genau einen Tick frei und nimmt ihn dann mit Priorität wieder zurück. Im Vergleich zu setTimeout(0) oder requestIdleCallback ist es deutlich präziser und priorisiert die fortsetzende Task vor neuen, niedrigeren Aufgaben.
Stand Mai 2026: Chrome/Edge ab 129, Firefox 138 (Mai 2026 stable), Safari 18.4 (April 2026). Für Browser ohne native Unterstützung gibt es einen einfachen Polyfill via MessageChannel.
isInputPending()
Wenn eine Task läuft und du wissen willst, ob der Nutzer gerade getippt hat — bevor du noch 100 ms weiterrechnest —, bietet die Scheduling-API isInputPending():
async function renderHeavy(items) {
for (const item of items) {
processItem(item);
if (navigator.scheduling?.isInputPending?.()) {
await scheduler.yield();
}
}
}
Du arbeitest weiter, solange der Nutzer ruhig ist, und gibst sofort frei, sobald ein Input ansteht. Das ist der präziseste Hebel für INP-kritische Pfade.
Debouncing/Throttling — der ehrliche Klassiker
Vor allen modernen APIs steht die nüchterne Wahrheit: Wenn ein Event-Handler bei jedem Tastendruck feuern muss, dann muss er nicht bei jedem Tastendruck feuern. 150–300 ms Debounce auf Such-Inputs sind kein Eingeständnis; sie sind die richtige Lösung für einen großen Teil der Cases.
const debouncedSet = useMemo(
() => debounce((v) => setFilter(v), 200),
[]
);
Tools 2026
Drei Werkzeuge gehören in den Werkzeugkasten jedes Frontend-Teams, das INP ernst nimmt:
PageSpeed Insights misst INP standardmäßig seit März 2024 und liefert sowohl Lab- (Lighthouse) als auch Field-Daten (CrUX) zum Vergleich. Wichtig: Lab-Daten unterschätzen INP systematisch, weil ein synthetischer Lauf weniger Interaktionen produziert als reale Nutzung.
web-vitals (JS-Library) in der aktuellen Major-Version (5.x, Mai 2026) liefert INP-Werte direkt im Browser, attribuiert pro Interaktion mit attribution-Payload:
import { onINP } from 'web-vitals';
onINP((metric) => {
console.log('INP', metric.value, 'ms');
console.log('Target:', metric.attribution.interactionTarget);
console.log('Long task duration:', metric.attribution.inputDelay);
}, { reportAllChanges: true });
Die attribution-Payload nennt das DOM-Element der teuersten Interaktion, die Input-Delay-Phase und die Presentation-Delay-Phase. Damit ist das Reporting nicht mehr „INP ist schlecht” — es ist „der Filter-Button auf Seite X braucht 480 ms”.
Chrome DevTools Performance-Tab markiert seit Chrome 122 (Februar 2024) Interaktionen explizit mit „INP”-Annotation in der Timeline. Aufnehmen, Interaktion ausführen, in der Timeline auf den INP-Marker klicken — DevTools zeigt die Phasen (Input-Delay, Processing, Presentation) und die längste blockierende Task.
Was bleibt
INP zwingt zu einer Disziplin, die unter FID optional war. Lazy-Loading allein reicht nicht mehr; Code-Splitting allein reicht nicht mehr; ein guter LCP reicht nicht mehr. Was zählt, ist die Reaktionsfähigkeit der Page über ihre gesamte Lebensdauer hinweg — vom ersten Klick bis zum letzten Filter-Update.
Das ist anstrengend, weil es die Mythologie der „schnellen Marketing-Page” zerstört. Eine Page, die in 1.2 s lädt und unter einer kontextuellen Filter-Interaktion 600 ms blockiert, ist nicht schnell. Sie ist schnell und langsam — und INP macht das sichtbar.
Die gute Nachricht: Die Werkzeuge sind alle da. startTransition, useDeferredValue, scheduler.yield(), isInputPending() — das sind keine experimentellen Features mehr. Sie sind seit zwei Jahren stabil, gut dokumentiert, mit klaren Best Practices. Was 2026 fehlt, ist nicht die Spec. Es ist die Routine, sie auf jedem PR mit Interaktion einzusetzen.
Genau das ist die Aufgabe, vor der jedes ernst zu nehmende Frontend-Team gerade steht.