Zum Inhalt springen
Grundlagen & Strategie

Performance-Budget im CI: Regressionen automatisch stoppen

Ein Performance-Budget als budget.json-Regel prüft in Lighthouse CI jeden Pull Request und stoppt den Build, sobald LCP, INP oder CLS die Schwelle reißen.

11 Min. Lesezeit Performance-BudgetLighthouse CICI/CDCore Web VitalsRegression

Eine Website wird selten in einem Zug langsam. Sie wird es Stück für Stück: ein neues Karussell auf der Startseite, ein zusätzliches Tracking-Skript, ein Hero-Bild in voller Auflösung, eine Bibliothek, die jemand für eine Kleinigkeit einbindet. Jede einzelne Änderung wirkt harmlos, doch in Summe rutschen die mühsam erreichten Core Web Vitals wieder aus dem grünen Bereich – meist unbemerkt, weil nach dem Deploy niemand misst. Genau hier setzt ein Performance-Budget an: Es legt vorab feste Obergrenzen für Ladezeit, Reaktionsschnelligkeit, Layoutstabilität und Seitengewicht fest und lässt eine Maschine bei jeder Änderung prüfen, ob diese Grenzen eingehalten werden. Als budget.json-Regel in Lighthouse CI wandert diese Prüfung direkt in den Entwicklungsprozess und stoppt den Build automatisch, sobald ein Wert die Schwelle reißt. Dass sich der Aufwand lohnt, zeigt schon eine Zahl aus der Praxis: Nur 62 Prozent (Web Almanac 2025) der mobilen Websites erreichen überhaupt ein gutes LCP unter 2,5 Sekunden. Dieser Beitrag zeigt, wie ein Budget aufgebaut ist, wie Lighthouse CI daraus einen Torwächter im Pull Request macht und wie Sie die Schwellen so kalibrieren, dass sie streng, aber nicht zickig sind. In unserer Core-Web-Vitals-Optimierung ist ein solches Budget der Baustein, der das Ergebnis dauerhaft absichert.

Das Wichtigste in Kürze

  • Ein Performance-Budget legt Obergrenzen vorab fest – für Ergebnis-Metriken wie LCP, INP und CLS und für Mengengerüste wie Kilobyte JavaScript oder Anzahl der Anfragen. Die Metriken schützen das Erlebnis, die Mengengrenzen schützen die Metriken.
  • Als gut gelten ein LCP unter 2,5 Sekunden (web.dev), ein INP unter 200 Millisekunden (web.dev) und ein CLS unter 0,1 (web.dev) am 75. Perzentil – doch nur 62 Prozent (Web Almanac 2025) der mobilen Websites erreichen ein gutes LCP.
  • Die Regeldatei budget.json beschreibt Zeit- und Ressourcengrenzen je Pfad und liegt versioniert im Repository. Zum Gate wird sie erst durch Lighthouse CI: Verletzt eine Messung eine als Fehler markierte Schwelle, endet der Lauf mit Fehlercode.
  • Schwellen brauchen einen bewussten Puffer und den Median aus mehreren Läufen. Ein Gate, das schon bei Messrauschen rot wird, verliert das Vertrauen des Teams und wird pauschal durchgewunken – dann ist es wertlos, obwohl es technisch funktioniert.
  • Das Budget misst im Labor und ersetzt die Felddaten nicht: Das INP ist dort nur über die Total Blocking Time annäherbar, das CLS wird nur bis zum Ende des Seitenaufbaus erfasst. Erst die Feldmessung zeigt, was echte Nutzer erleben.

Warum jeder Deploy die Core Web Vitals unbemerkt verschlechtert

Performance ist keine Eigenschaft, die man einmal herstellt und die dann bleibt. Sie ist ein Zustand, der bei jeder Codeänderung neu auf dem Spiel steht. Das Tückische an Performance-Regressionen ist, dass sie schleichend passieren und keinen sichtbaren Fehler erzeugen: Die Seite funktioniert weiterhin, sie lädt nur etwas langsamer, reagiert etwas träger oder verschiebt beim Aufbau kurz das Layout. Für die Person, die die Änderung eingecheckt hat, sieht auf dem schnellen Büro-Rechner mit stabilem Netz alles gut aus. Erst die echten Nutzer auf Mittelklasse-Smartphones im Mobilfunknetz spüren die Verschlechterung – und die tauchen in keinem Fehlerbericht auf, sondern springen einfach ab.

Die wirtschaftlichen Folgen sind gut belegt. Schon 0,1 Sekunden (Deloitte) schnellere Ladezeit steigerten in einer branchenübergreifenden Analyse die Conversions im Handel um 8,4 Prozent (Deloitte). Umgekehrt steigt die Wahrscheinlichkeit, dass ein Nutzer die Seite wieder verlässt, um 32 Prozent (Google/SOASTA), wenn die Ladezeit von einer auf drei Sekunden wächst. Und die Conversion-Rate sinkt laut einer Auswertung von Millionen Seitenaufrufen um rund 4,4 Prozent (Portent) mit jeder zusätzlichen Sekunde in den ersten fünf Sekunden. Jede unbemerkte Regression kostet also messbar Geld. Der klassische Gegenmittel-Reflex – alle paar Monate ein großes Performance-Audit – kommt für diese kleinen, kontinuierlichen Verschlechterungen zu spät: Bis zum nächsten Audit haben sich Dutzende Mini-Regressionen aufsummiert, und niemand weiß mehr, welche Änderung welchen Anteil hatte.

Ein Performance-Budget dreht die Logik um. Statt Verschlechterungen im Nachhinein zu suchen, verhindert es sie beim Entstehen. Es macht Performance zu einer Bedingung, die jede Änderung erfüllen muss, bevor sie in den Hauptzweig darf – so wie automatisierte Tests dafür sorgen, dass eine Änderung keine bestehende Funktion zerstört. Wer die drei Core Web Vitals im Zusammenhang verstehen möchte, findet die Einordnung im Beitrag zu den Core Web Vitals 2026; hier geht es darum, wie man ihre Einhaltung dauerhaft erzwingt.

Was ein Performance-Budget ist und was es misst

Ein Performance-Budget ist eine Sammlung von Obergrenzen, die eine Seite nicht überschreiten darf. Diese Grenzen betreffen zwei Arten von Werten. Zum einen die Ergebnis-Metriken, also das, was der Nutzer erlebt: das Largest Contentful Paint (LCP) für die Ladezeit, das Interaction to Next Paint (INP) für die Reaktionsschnelligkeit und das Cumulative Layout Shift (CLS) für die visuelle Stabilität. Als gut gelten ein LCP unter 2,5 Sekunden (web.dev), ein INP unter 200 Millisekunden (web.dev) und ein CLS unter 0,1 (web.dev), jeweils gemessen am 75. Perzentil (web.dev) der Seitenaufrufe. Zum anderen die Mengengerüst-Budgets, die Ursachen begrenzen: wie viele Kilobyte JavaScript, Bilder oder Schriften eine Seite laden darf und wie viele Anfragen sie absetzt.

Der Unterschied ist wichtig. Ergebnis-Metriken sagen, ob es dem Nutzer zu langsam ist; Mengengerüst-Budgets sagen, warum. Ein JavaScript-Budget von beispielsweise 400 Kilobyte pro Seite fängt eine Regression oft früher ab als eine Metrik, weil zusätzlicher Code in aller Regel zuerst das Gewicht erhöht und erst danach die Reaktionszeit. Beide Budget-Arten ergänzen sich deshalb: Die Metriken schützen das Erlebnis, die Mengengrenzen schützen die Metriken. Wie man ein reines Ressourcen-Budget für Skripte und Medien aufsetzt und pflegt, vertieft der Beitrag zu den JavaScript-Performance-Budgets.

Labor- und Feldmetriken im Budget

Ein Budget prüft im CI zunächst Labordaten aus einer kontrollierten Messung. Das INP lässt sich im Labor nicht direkt erheben, weil es echte Interaktionen braucht – deshalb nutzt Lighthouse die Total Blocking Time (TBT) als Labor-Stellvertreter. Eine niedrige TBT ist ein starkes Signal für ein gutes INP im Feld. Das CLS wiederum wird im Labor nur bis zum Ende des Seitenaufbaus erfasst, im Feld dagegen über die gesamte Sitzung. Ein CI-Budget ersetzt daher die Feldmessung nicht, sondern fängt Regressionen ab, bevor sie überhaupt beim Nutzer ankommen.

budget.json: die Regeldatei für Ressourcen und Metriken

Das Herzstück ist eine schlichte Textdatei namens budget.json. Sie beschreibt in einem klar lesbaren Format, welche Obergrenzen gelten – getrennt nach Zeit-Metriken (timings) und Ressourcen-Mengen (resourceSizes und resourceCounts). Jede Regel bezieht sich auf einen Pfad, sodass sich unterschiedliche Seitentypen unterschiedlich behandeln lassen. Die Datei liegt im Repository neben dem Code und wird damit selbst versioniert: Jede Änderung am Budget ist nachvollziehbar, und das Budget durchläuft dieselben Reviews wie der Rest des Projekts.

budget.json
[
  {
    "path": "/*",
    "timings": [
      { "metric": "largest-contentful-paint", "budget": 2500 },
      { "metric": "total-blocking-time", "budget": 200 },
      { "metric": "speed-index", "budget": 3400 }
    ],
    "resourceSizes": [
      { "resourceType": "script", "budget": 400 },
      { "resourceType": "image", "budget": 500 },
      { "resourceType": "total", "budget": 1000 }
    ]
  }
]

In diesem Beispiel darf das LCP höchstens 2.500 Millisekunden betragen, die Total Blocking Time höchstens 200 Millisekunden, und das ausgelieferte JavaScript höchstens 400 Kilobyte. Lighthouse liest diese Datei, vergleicht die gemessenen Werte mit den Budgets und markiert jeden Posten, der darüber liegt, als über Budget. Das allein stoppt allerdings noch keinen Build – es erzeugt nur einen Bericht. Damit aus dem Bericht ein echtes Gate wird, braucht es einen zweiten Baustein: Lighthouse CI.

Lighthouse CI als Torwächter im Pull Request

Lighthouse CI (die quelloffene Werkzeugkette GoogleChrome/lighthouse-ci) ist die Brücke zwischen einem Lighthouse-Bericht und Ihrer Pipeline. Es besteht aus drei Schritten: collect sammelt die Messungen, indem es Lighthouse mehrfach gegen die definierten Adressen laufen lässt; assert vergleicht die Ergebnisse mit festgelegten Schwellen; und upload legt die Berichte ab, wahlweise auf einem eigenen LHCI-Server für den Langzeitverlauf. Entscheidend für das Gate ist der assert-Schritt: Verletzt eine Messung eine als error markierte Schwelle, beendet sich das Werkzeug mit einem Fehlercode ungleich null. In jeder CI-Umgebung – ob GitHub Actions, GitLab CI oder eine andere Pipeline – bedeutet ein solcher Fehlercode: Der Lauf ist rot, der Check schlägt fehl, der Merge wird blockiert.

lighthouserc.json
{
  "ci": {
    "collect": {
      "url": ["https://example.com/"],
      "numberOfRuns": 3
    },
    "assert": {
      "assertions": {
        "categories:performance": ["error", { "minScore": 0.9 }],
        "largest-contentful-paint": ["error", { "maxNumericValue": 2500 }],
        "total-blocking-time": ["error", { "maxNumericValue": 200 }],
        "cumulative-layout-shift": ["error", { "maxNumericValue": 0.1 }]
      }
    }
  }
}

Diese Konfiguration verlangt eine Performance-Note von mindestens 0,9 und setzt harte Grenzen für LCP, TBT und CLS. Man kann die budget.json und die Assertions kombinieren: Die eine deckt die Ressourcen-Mengen ab, die andere die Ergebnis-Metriken und die Gesamtnote. Wichtig ist, dass die Prüfung nicht auf dem Rechner der Entwicklerin läuft, sondern in der Pipeline – reproduzierbar, mit gedrosseltem Netz und gedrosselter CPU, wie es Lighthouse für die mobile Messung standardmäßig annimmt. Nur so entspricht das Laborergebnis grob dem, was Nutzer auf schwächeren Geräten erleben.

Ein Gate pro Pull Request

Lighthouse CI läuft automatisch bei jedem Pull Request, noch bevor der Code den Hauptzweig erreicht. Reißt ein Budget, wird die Prüfung rot und der Merge lässt sich nicht abschließen, bis die Ursache behoben ist.

Median aus mehreren Läufen

Statt einer einzelnen, verrauschten Messung bildet Lighthouse CI den Median aus mehreren Durchläufen. Das dämpft zufällige Ausreißer und macht die Schwelle verlässlich genug, um sie hart zu erzwingen.

Verlauf statt Momentaufnahme

Der optionale LHCI-Server speichert jeden Lauf und zeigt den zeitlichen Verlauf. So wird sichtbar, ob sich eine Metrik über viele kleine Schritte langsam vom Ziel entfernt, lange bevor sie das Budget reißt.

Schwellen richtig kalibrieren: streng, aber nicht zickig

Ein Budget ist nur so nützlich wie seine Schwellen. Sind sie zu locker, rutschen Regressionen durch und das Gate wiegt in falscher Sicherheit. Sind sie zu streng oder zu nah an der aktuellen Messung, schlägt der Build schon bei normalem Messrauschen fehl – und ein Team, das ständig rote Läufe ohne echten Grund sieht, gewöhnt sich an, sie zu ignorieren. Ein gutes Budget beginnt deshalb bei den offiziellen Zielwerten und lässt einen kleinen, bewussten Puffer. Der Median aus mehreren Läufen und ein Warn-Level unterhalb der harten Fehlergrenze helfen, das Rauschen von echten Verschlechterungen zu trennen.

MetrikGutes ZielBudget im CI (Vorschlag)Typische Regressionsursache
LCPunter 2,5 s (web.dev)max. 2,5 s, Warnung ab 2,2 sNeues Hero-Bild ohne Preload, langsamere Serverantwort
INP / TBTunter 200 ms (web.dev)TBT max. 200 msZusätzliches Drittanbieter-Skript, ungeteilte lange Aufgabe
CLSunter 0,1 (web.dev)max. 0,1Anzeige oder Banner ohne reservierten Platz
JavaScript-Gewichtschlank haltenmax. 400 KB pro SeiteNeue Bibliothek, doppelt gebündeltes Framework
Gesamtgewichtso klein wie möglichmax. 1 MB pro SeiteUnkomprimierte Medien, viele Drittanbieter-Anfragen

Wichtig ist außerdem, das Budget pro Seitentyp zu differenzieren. Die Startseite, eine Kategorieseite, eine Produktseite und ein Blogartikel haben völlig verschiedene Realitäten: Was für eine textlastige Artikelseite großzügig ist, wäre für eine bildlastige Produktseite unrealistisch eng. Deshalb erlaubt die budget.json unterschiedliche Regeln je Pfad. Ein häufiger Auslöser für gerissene Budgets sind Drittanbieter-Skripte, die sich über Tag-Manager unbemerkt einschleichen; wie man diese Last gezielt reduziert, behandelt der Beitrag zum Entschlacken von Drittanbieter-Skripten.

Ein zu zickiges Gate ist schlimmer als keines

Wenn ein Build durch harmloses Messrauschen rot wird, verliert das Team schnell das Vertrauen in die Prüfung und beginnt, rote Läufe pauschal durchzuwinken. Damit ist das Gate wertlos, obwohl es technisch funktioniert. Setzen Sie die harte Fehlergrenze deshalb mit etwas Abstand zur aktuellen Messung, nutzen Sie den Median aus mindestens drei Läufen und trennen Sie Warnungen von Fehlern. Ziel ist ein Gate, das nur bei echten Verschlechterungen anschlägt – dann wird jeder rote Lauf ernst genommen.

Vom roten Build zur grünen Pipeline: der Ablauf

In der Praxis fügt sich das Budget in den ganz normalen Entwicklungsablauf ein. Jemand öffnet einen Pull Request, die Pipeline startet, baut die Seite, lässt Lighthouse CI gegen die relevanten Adressen laufen und vergleicht die Ergebnisse mit dem Budget. Bleiben alle Werte im Rahmen, wird der Check grün und die Änderung kann zusammengeführt werden. Reißt ein Budget, wird der Check rot, und der Bericht zeigt genau, welche Metrik oder welche Ressource über der Grenze liegt. Die verantwortliche Person sieht das noch vor dem Merge und kann die Ursache im überschaubaren Diff des Pull Requests suchen, statt später im gewachsenen Gesamtsystem.

  1. Ein Budget je Seitentyp festlegen – Startseite, Kategorie, Produkt und Artikel haben unterschiedliche Realitäten
  2. budget.json und die Lighthouse-CI-Konfiguration ins Repository legen, damit jede Änderung sie durchläuft
  3. Die Prüfung als Pflicht-Check im Pull Request verankern, sodass ein roter Lauf den Merge blockiert
  4. Mehrere Läufe pro Messung nehmen und den Median werten, um zufälliges Rauschen auszublenden
  5. Bei einem gerissenen Budget die betroffene Metrik im Bericht öffnen und die Ursache im Diff suchen
  6. Das Budget regelmäßig nachziehen: Wird eine Seite dauerhaft schneller, wird die Schwelle strenger

Der Kern in einem Satz

Ein Performance-Budget verlagert die Qualitätskontrolle vom guten Vorsatz in die Pipeline: Nicht der Mensch muss nach jedem Deploy daran denken zu messen, sondern der Build stoppt von selbst, sobald eine Metrik das Budget reißt.

Der Nebeneffekt ist kulturell so wertvoll wie technisch. Sobald das Gate steht, wird Performance zur geteilten Verantwortung des ganzen Teams statt zur Aufgabe einer einzelnen Person, die alle paar Monate aufräumt. Weil die Rückmeldung sofort im Pull Request kommt, lernt jede Entwicklerin unmittelbar, welche Muster teuer sind – ein spät geladenes Hero-Bild, ein ungeteilter langer Task, eine schwere Bibliothek. Wie man solche langen Aufgaben mit scheduler.yield gezielt aufteilt und Bremsen einzelner Frames aufspürt, zeigen zwei vertiefende Beiträge zur Interaktivität.

Was ein Budget nicht ersetzt: die Felddaten

So wirksam ein CI-Budget ist – es misst im Labor, nicht bei echten Nutzern. Das Labor liefert reproduzierbare Werte unter kontrollierten Bedingungen und ist deshalb ideal, um Regressionen zwischen zwei Ständen zu erkennen. Was echte Menschen auf ihren Geräten und in ihren Netzen erleben, zeigen aber nur Felddaten. Und der Unterschied ist wirtschaftlich relevant: Wächst die Ladezeit von einer auf fünf Sekunden, steigt die Absprungwahrscheinlichkeit um 90 Prozent (Google/SOASTA), und im Reisesegment brachten schon 0,1 Sekunden schnelleres Laden 10,1 Prozent (Deloitte) mehr Conversions. Diese Effekte entstehen im Feld, nicht im Labor.

Deshalb gehören Labor-Budget und Feldmessung zusammen: Das Budget im CI verhindert, dass eine Regression überhaupt live geht; die Feldmessung bestätigt, dass sich die Werte auch bei echten Nutzern halten. Wie sich Labor- und Felddaten – also Lighthouse-Läufe, RUM und die CrUX-Daten von Google – sinnvoll zu einer Gesamtstrategie verbinden lassen, vertieft der Beitrag zu RUM, CrUX und Performance-Budgets. Und weil das INP im Labor nur über die TBT annäherbar ist, lohnt der ergänzende Blick auf die INP-Optimierung im Detail.

Ein Budget im CI verändert die Kultur im Team: Performance ist keine einmalige Aktion mehr, die nach ein paar Monaten verpufft, sondern eine Bedingung, die jeder Pull Request erfüllen muss – automatisch geprüft, bevor irgendjemand es vergisst.

Projekterfahrung aus 50+ Performance-Projekten

Genau so gehen wir bei der Einrichtung vor: Wir bestimmen die kritischen Seitentypen, kalibrieren realistische Budgets für LCP, INP und CLS, verankern Lighthouse CI als Pflicht-Check in Ihrer Pipeline und begleiten das Team, bis rote Läufe als hilfreiches Signal und nicht als Störung verstanden werden. Welche Leistungen dazugehören, zeigt unsere Übersicht der Performance-Leistungen; für die konkreten Frontend-Hebel, mit denen sich ein gerissenes Budget wieder einfangen lässt, hilft die Frontend-Optimierung.

Dieser Artikel basiert auf Daten aus: web.dev (Core Web Vitals, Google Chrome), Lighthouse und Lighthouse CI (GoogleChrome/lighthouse-ci), dem Web Almanac 2025 (HTTP Archive), Deloitte (Milliseconds Make Millions), Google/SOASTA (Mobile Page Speed Benchmarks) und Portent (Site Speed and Conversion). Alle genannten Statistiken wurden zum Zeitpunkt der Veröffentlichung geprüft.

Verwandte Artikel

Grundlagen & Strategie

Tempo festschreiben: Performance in der Ausschreibung

Wie Ladezeit zum Abnahmekriterium wird: Zielwert, Messmethode, Datenquelle und Nachweiszeitpunkt je Kennzahl – und was das Werkvertragsrecht daraus macht.

14 Min. Lesezeit
Frontend-Optimierung

View Transitions API: Nahtlose Seitenwechsel im Shop

Native, GPU-beschleunigte Seitenwechsel im Shop ohne JavaScript-Framework: Wie Cross-Document View Transitions den Sprung von Kategorie zu Produkt glätten.

12 Min. Lesezeit
Core Web Vitals & Messung

Lange Tasks aufteilen: INP mit scheduler.yield senken

Lange JavaScript-Tasks über 50 ms mit scheduler.yield() in Häppchen zerlegen, den Hauptthread zwischen den Chunks freigeben und den INP unter 200 ms halten.

12 Min. Lesezeit