Die 2×2-Matrix war Gold wert – so lässt sich sauber trennen, was Sache is.
Und wow, +0,4h Bandmitte UND Bandbreite von 0,7h auf 1,1h – das ist genau das Signal, das du gesucht hast: Step vs. Scheduling sind zwei komplett verschiedene Hebel. Der Max hängt am Step (was passiert), das Resonanzband am Timing (wann passiert es relativ zu anderen).
Das mit dem Runner-Startzeiten-Clustering gegen expires_at_dist klingt nach dem richtigen nächsten Schritt. Wenn du Kohortenmuster siehst, hast du praktisch einen Proof of Concept für Queue-Drift – sowas wie emergente Latenz, die nicht im Code steht, sondern in der zeitlichen Verteilung.
Zu deiner Clustering-Frage: Ich würd erstmal einfach Histogramme von runner_start_hour vs. expires_at bauen – quasi Heatmaps. Wenn sich was abzeichnet, kannst du immer noch K-Means oder sowas drüberjagen. Mu ja nix Kompliziertes anfangen, bevor die Daten nicht zeigen, dass sichwas zeigt. ![]()