Skip to content

Vorhersagen, welche Pull Requests hängen bleiben — mit der Baseline Ihres Teams

Aliaume Caplat Gründer, DevPrism LinkedIn
pull-requests engineering-metrics dora engineering-management

Jedes Team führt irgendwann dieselbe Automatisierung ein: „Sag mir Bescheid, wenn ein Pull Request länger als 48 Stunden offen ist.“

Und jedes Team schaltet sie irgendwann wieder ab.

Nicht, weil liegengebliebene PRs plötzlich egal wären. Sondern weil 48 Stunden die Zahl von jemand anderem ist. In einem Team, das innerhalb von zwei Stunden reviewt, kommt die Meldung viel zu spät, um zu nützen. In einem Team, das zweimal pro Woche reviewt, feuert sie auf alles, jeden Tag — bis jemand den Kanal stummschaltet.

Ein Schwellenwert muss irgendwoher kommen. Der Fehler ist, ihn von Hand zu wählen.

Der Perspektivwechsel: eine PR mit Ihrem Team vergleichen, nicht mit einer Konstante

Die Frage „ist diese PR zu spät?” hat keine absolute Antwort. Nur eine relative: zu spät gemessen an dem, was dieses Team normalerweise schafft.

Diese Umformulierung macht aus einer Meinung eine Berechnung. Die Daten haben Sie längst: Jeder gemergte Pull Request ist eine Beobachtung, wie lange ein Review in Ihrem Team tatsächlich dauert. Machen Sie aus diesen Beobachtungen eine Verteilung — und der Schwellenwert wählt sich selbst.

Zwei Messgrößen zählen, und sie sind nicht dasselbe:

Messgröße Definition Was sie aussagt
Pickup Time PR geöffnet → erstes Review Wie lange Code auf einen Menschen wartet
Cycle Time PR geöffnet → geschlossen / gemergt Der ganze Weg, inklusive Arbeit des Autors

Auf die Pickup Time lohnt es sich zu alarmieren. Die Cycle Time enthält den Autor, der auf Kommentare antwortet, rebased, auf die CI wartet — legitime laufende Arbeit. Die Pickup Time misst etwas anderes: Es hat noch niemand hingeschaut. Das ist Wartezeit, das ist reine Verschwendung — und anders als bei der Cycle Time kann jemand anderes als der Autor etwas dagegen tun.

Schritt 1 — Die Baseline berechnen

Nehmen Sie Ihre gemergten Pull Requests aus einem gleitenden Zeitfenster und berechnen Sie das 50., 75. und 90. Perzentil der Pickup Time.

In diesem einen Satz stecken vier Entscheidungen, und jede einzelne entscheidet über Signal oder Rauschen.

percentile_disc verwenden, nicht percentile_cont

percentile_cont interpoliert zwischen zwei Beobachtungen. Bei einer Stichprobe von zwölf PRs erfindet das eine Dauer, die es nie gab — ein P75 von „26,4 Stunden”, obwohl Ihr Team noch nie 26,4 Stunden gebraucht hat. percentile_disc gibt eine echte Beobachtung zurück. Wenn Sie später sagen „das überschreitet das P75 Ihres Teams”, sollte diese Zahl etwas sein, das tatsächlich passiert ist.

Wartungs-Bots ausschließen

Bots für Abhängigkeits-Updates öffnen viele PRs und lassen viele davon liegen. Bleiben sie in der Stichprobe, dominieren sie die Verteilung und verzerren genau das menschliche Signal, das Sie messen wollen. Stellen Sie sich einen Dependency-Bot vor, der jede Woche ein paar Versionssprünge öffnet, von denen die meisten automatisch gemergt, vom nächsten Sprung überholt oder kommentarlos geschlossen werden. Seine Laufzeiten beschreiben einen Prozess, den nie ein Mensch durchlaufen hat — und weil er weit mehr PRs öffnet als jede einzelne Person, kann ein einziges Bot-Konto in der Stichprobe schwerer wiegen als Ihr gesamtes Team. Die hätte ohnehin niemand reviewt. Das ist keine Review-Schuld.

Unterhalb einer Mindeststichprobe die Antwort verweigern

Unter etwa zehn gemergten PRs im Zeitfenster sind Perzentile Rauschen im Gewand von Präzision. Ein P90 aus vier Beobachtungen ist schlicht „die langsamste von vieren”. Das richtige Verhalten ist, nichts auszugeben: keine Baseline, keine Vorhersage, keine Meldung.

Darauf sei ausdrücklich hingewiesen, denn es ist das Gegenteil dessen, was die meisten Dashboards tun. Ein Werkzeug, das immer eine Zahl liefert, bringt seinen Nutzern bei, dass seine Zahlen nichts bedeuten. Die Antwort zu verweigern ist ein Feature — und die billigste Glaubwürdigkeit, die Sie je bekommen werden.

Die Baseline pro Team berechnen

Ein Plattform-Team und ein Mobile-Team teilen weder Review-Kultur noch Zeitzone noch Definition von dringend. Ein globales Perzentil presst beide in eine Zahl, die keines von beiden beschreibt.

Die Abfrage, falls Sie es nachbauen wollen

Nichts davon setzt ein Werkzeug voraus. Wenn Ihre Pull-Request-Historie in einem Data Warehouse liegt, passt die ganze Baseline in eine Abfrage — überspringen Sie sie sonst, der Rest des Artikels trägt auch ohne.

SELECT
  percentile_disc(0.50) WITHIN GROUP (ORDER BY pickup_hours) AS p50,
  percentile_disc(0.75) WITHIN GROUP (ORDER BY pickup_hours) AS p75,
  percentile_disc(0.90) WITHIN GROUP (ORDER BY pickup_hours) AS p90,
  count(*)                                                   AS sample_size
FROM (
  SELECT EXTRACT(EPOCH FROM (first_review_at - created_at)) / 3600 AS pickup_hours
  FROM pull_requests
  WHERE merged_at BETWEEN :period_start AND :period_end
    AND first_review_at IS NOT NULL
    AND author NOT IN (SELECT login FROM maintenance_bots)
) AS observed;

Schritt 2 — Die offenen Pull Requests bewerten

Gehen Sie nun die offenen PRs durch. Nehmen Sie für jede die seit der Eröffnung verstrichene Zeit und ordnen Sie sie in die Verteilung ein:

verstrichen < P50            → im Plan          (nichts ausgeben)
P50 ≤ verstrichen < P75      → wird langsamer
P75 ≤ verstrichen < P90      → gefährdet
verstrichen ≥ P90            → absehbarer Blocker

Zwei Regeln machen das in der Praxis brauchbar.

Jede PR überspringen, die bereits ein erstes Review hat. Sobald ein Mensch eingestiegen ist, steht die PR nicht mehr in der Warteschlange — sie ist in Arbeit. Darauf zu alarmieren erzeugt genau den Fehlalarm, der am Ende die ganze Integration stummschaltet. Diese eine Bedingung entfernt den größten Teil des Rauschens.

Zu PRs unterhalb des P50 nichts sagen. Rund die Hälfte Ihrer offenen PRs liegt konstruktionsbedingt im Plan. Sie zu melden erhöht das Volumen und senkt die Aufmerksamkeit.

Und wenn Sie etwas ausgeben, benennen Sie den Vergleich:

Kein Review nach 31,4 h — überschreitet das Team-P75 (26 h). Gefahr einer Blockade.

Nicht „diese PR ist gefährdet”. Die Zahl, an der gemessen wird, muss in der Meldung stehen — sonst ist die Meldung ein Autoritätsargument statt eines Arguments. Außerdem wird sie so widerlegbar: Jeder kann nachprüfen, ob 26 Stunden wirklich das eigene P75 sind. Genau darum geht es.

Was das nicht aussagt

Ein Modell, das man nicht kritisieren kann, sollte man nicht ausliefern. Vier ehrliche Grenzen:

Die Baseline beruht auf den Überlebenden. Sie zählt nur PRs, die reviewt und gemergt wurden. Die, die nach drei Wochen Verrotten abgebrochen wurden, tragen nichts bei — die Verteilung ist also systematisch optimistischer als die tatsächliche Erfahrung des Teams. Das macht die Meldung konservativ: Wenn sie feuert, bedeutet sie etwas.

Die Baseline driftet mit dem Team. Ein Quartal schlechter Review-Hygiene hebt das P75, und ein höheres P75 macht die Meldung leiser. Die Messung passt sich dem Verfall an, statt ihn zu berichten. Verfolgen Sie deshalb die Baseline selbst über die Zeit, als eigenständige Kennzahl: Ein P90, das sich in zwei Monaten verdoppelt, ist der Befund — und keine PR-Meldung wird ihn Ihnen zeigen.

Sie sagt einen bestimmten Fehlerfall voraus. Das Hängenbleiben vor dem ersten Review, mehr nicht. Sie sagt nichts darüber, ob der Code korrekt ist, ob die PR zu groß ist oder ob die CI gleich fehlschlägt. Sie ist ein Signal unter mehreren, kein Risiko-Score.

Kleine Teams bekommen verrauschte Perzentile. Zehn Beobachtungen sind eine Untergrenze, kein Komfort. Bei kleiner Stichprobe lieber das Zeitfenster verlängern als den Schwellenwert verschärfen.

Warum sich der Aufwand lohnt

Ein fester Schwellenwert ist eine Richtlinie: Jemand hat 48 Stunden festgelegt. Eine Perzentil-Baseline ist eine Messung: Ihr Team hat es festgelegt, durch seine Arbeit.

Dieser Unterschied wiegt schwerer als der Genauigkeitsgewinn. Eine Meldung, die sagt „das überschreitet die Zahl, mit der ich konfiguriert wurde”, lädt zur Diskussion über die Konfiguration ein. Eine Meldung, die sagt „das überschreitet das, was Ihr Team in drei von vier Fällen schafft”, lädt zum Gespräch über die Warteschlange ein — und das war das Gespräch, das Sie führen wollten.

Wie DevPrism es macht

DevPrism berechnet diese Baseline bei jeder Synchronisierung pro Team und bewertet die offenen Pull Requests daran:

  • Perzentile für Pickup Time und Cycle Time aus Ihren gemergten PRs, ohne Wartungs-Bots
  • Diskrete Perzentile, sodass jeder Schwellenwert eine Dauer ist, die Ihr Team wirklich erreicht hat
  • Keine Vorhersage unterhalb der Mindeststichprobe und bei PRs, die bereits im Review sind
  • Jede markierte PR trägt ihr Verhältnis zur Baseline und eine Begründung, die das überschrittene Perzentil benennt
Offene Pull Requests, bewertet an der Baseline des eigenen Teams — die markierten tragen das überschrittene Perzentil, keine generische Warnung.

Der Sinn des Ganzen ist nicht, die Zukunft vorherzusagen. Sondern aufzuhören, von jeder Engineering-Führungskraft zu verlangen, sich eine Zahl auszudenken — und die Meldung gegenüber demjenigen vertretbar zu machen, der sie erhält.


Sie möchten diese Baseline pro Team aus Ihrer eigenen Historie berechnet bekommen? DevPrism kostenlos testen — vollständige PR Intelligence und Risk Scoring gehören zum Pro-Plan, im 14-tägigen Test enthalten, ohne Kreditkarte.