- Auf jumpcomedy.com schlugen gegen 22 Uhr alle HTTP-POST-Aufrufe von RTK Query fehl, wodurch Website-Funktionen ausfielen; lokal funktionierte alles, was die Ursachenanalyse erschwerte
- Während sich Kundenbeschwerden häuften, musste der Betreiber den Ausfall allein bewältigen – ohne Production Support, SRE, Senior Engineers oder Manager
- Der TypeError des Browsers im Zusammenhang mit
fetchlieferte keinen direkten Hinweis, zumal GET und DELETE normal funktionierten - Auch Prüfungen von Sentry, Produktionsdatenbank, Cloudflare, Chrome-Update und Rollback auf ältere Versionen brachten keine Veränderung; erst als der lokal leer gelassene PostHog api_key eingetragen wurde, ließ sich das Problem reproduzieren
- Nach dem Entfernen von PostHog funktionierte alles wieder; später bestätigten GitHub-Issues bei PostHog und Redux Toolkit denselben Ausfall, womit sich der Einfluss eines externen Tools zeigte
Der Druck durch den Ausfall
- Auf jumpcomedy.com schlugen ab etwa 22 Uhr alle HTTP-POST-Aufrufe auf Basis von RTK Query fehl, sodass zentrale Funktionen nicht mehr richtig arbeiteten
- Es gab zwar kürzlich deployte Änderungen, aber nichts, was als Ursache nahelag; da sich das Problem lokal nicht reproduzieren ließ, wurde die Fehlersuche noch schwieriger
- Der Betreiber bat im NextJS- und Vercel-Discord um Hilfe, erhielt jedoch keine Antwort, und es gab auch keine Production-Support-Organisation, an die er die Störungsbehebung hätte übergeben können
- Kunden-E-Mails häuften sich weiter
- Anfragen, dass sich Veranstaltungspreise nicht ändern ließen
- Anfragen, dass sich Promo-Codes nicht entfernen ließen
- Weil kleine Geschäftskunden auf den Dienst angewiesen waren, empfand der Betreiber Scham, Traurigkeit, ein Gefühl der Unfähigkeit und Impostor-Syndrom
Debugging-Prozess und Ursachenbestätigung
- Der Browserfehler war ein TypeError, wonach
fetchmit einem bereits verwendeten Request-Object ausgeführt wurde, zeigte aber nicht auf die tatsächliche Ursache - Mit mehreren
console.log()-Ausgaben und Breakpoints wurden Header, Länge des API-Tokens, Aufrufreihenfolge und Ähnliches überprüft, ohne zu einer klaren Ursache zu führen - Ein Chrome-Update wurde als mögliche Ursache vermutet, doch das Problem ließ sich auch in Firefox und Edge reproduzieren, sodass es kein reines Browserproblem war
- Auch ein Zurückrollen auf ältere Versionen änderte nichts
- Fehler auch mit der Version von vor einem Monat
- Fehler auch mit der Version von vor drei Monaten
- Fehler auch mit der Version von vor einem Jahr
- Um die Unterschiede zwischen lokaler Umgebung und Produktion zu verringern, wurden mehrere Kandidaten geprüft
- Sentry in Produktion entfernt: keine Veränderung
- Lokale Umgebung mit der Produktionsdatenbank verbunden: keine Veränderung
- Cloudflare deaktiviert: keine Veränderung
- Lokal war aus Kostengründen der PostHog api_key leer gelassen worden; nachdem er hinzugefügt wurde, trat dasselbe Problem auf
- Im nächsten Commit wurde PostHog entfernt, woraufhin alle Funktionen wieder normal liefen
- Dasselbe Problem wurde später auch durch GitHub-Issues bestätigt
1 Kommentare
Hacker-News-Kommentare
Nachdem ich ein Jahr lang als SRE in einem großen globalen Unternehmen gearbeitet habe, konnte ich aus dem im Text beschriebenen „Panik“-Modus herauskommen
Aus Geschäftssicht wirkt jedes Problem wie ein Weltuntergangsereignis, und in so einer Situation gerät man leicht in Panik, aber tatsächlich ist es nur selten so schlimm, und selbst wenn es schlimm ist, überlebt man es meistens unbeschadet
In solchen Situationen ist der Schlüssel, 5–10 Minuten innezuhalten und sich die Lage so klar wie möglich zu vergegenwärtigen, bevor man sofort versucht, etwas zu reparieren. Angst behindert vernünftiges Urteilsvermögen, und wenn man im Panikzustand wahllos auf Knöpfe drückt, kann sich das Problem noch mehr verheddern. Mein Trick ist, mir eiskaltes Wasser ins Gesicht und über die Hände zu werfen, um den Angstkreislauf zu unterbrechen
Wenn man so etwas ein paar Mal erlebt hat, merkt man, dass es besser zu bewältigen ist als gedacht, und gewinnt das Selbstvertrauen, schon früher mit schlimmen Situationen fertig geworden zu sein, sodass man weiß, dass man damit klarkommt, auch wenn niemand da ist, den man um Hilfe bitten kann
Etwa wenn gekaufte Software wegen Fehlbesetzung oder misslungener Konfiguration gar nichts leistet, wenn Mitarbeitende jedes Jahr Tausende Stunden durch schlechte User Experience und sinnlose Anforderungen verlieren, wenn Fähigkeiten brachliegen und nichts bewirken, wenn nutzlose Meetings täglich Zeit verschwenden, wenn Funktionen nur existieren, um Audit-Anforderungen zu erfüllen, oder wenn Führungskräfte weiter Geld der Firma verschwenden
Downtime wirkt nicht schlimmer als diese Probleme, zieht aber viel mehr Aufmerksamkeit und Panik auf sich. Es fühlt sich an wie der Vergleich zwischen Terror und Herzkrankheiten. Das Unternehmen kümmert sich nicht um deinen Schlaf oder deine psychische Gesundheit und wird so viel Druck machen, wie es kann. Das heißt nicht, dass es böswillig ist, aber in diesem Punkt ist es wie ein Tyrann: Es drängt umso mehr, je weiter du nachgibst
Eines meiner Programmiermottos lautet: „Keine schwarze Magie.“ Wenn ich nicht verstehe, warum etwas funktioniert, dann ist es nicht fertig
Genauso sehe ich Incident Response. Wenn jemand nicht schlüssig erklären kann, warum sein Vorschlag Wirkung haben sollte, dann sollte man ihn meiner Meinung nach nicht umsetzen. Irgendwann mag ein Moment kommen, in dem man einfach abdrücken muss, aber rückblickend scheint es bei mir nie wirklich so einen Fall gegeben zu haben
Es war ziemlich schockierend zu sehen, wie normalerweise sehr ruhige leitende Angestellte während eines Ausfalls anfingen, irgendwelche willkürlichen Fix-Kandidaten in den Raum zu werfen
Man stelle sich vor, wie viel größer der Schaden geworden wäre, wenn niemand diesen Solo-Entwickler gestoppt hätte, als er versuchte,
fetchmodern zu machenEs stimmt, dass Angst vernünftiges Urteilsvermögen behindert, und ich möchte noch hinzufügen, dass Angst extrem ansteckend ist. Wenn die Leute an der Front sehen, dass Führungskräfte, Manager oder Kolleginnen und Kollegen in Panik geraten, geraten sie oft ebenfalls in Panik. Zum Glück blieb mein VP immer ruhig und stellte Klarheit über Aktionismus
Ich weiß nicht, ob das wirklich ein mentaler Zusammenbruch ist, und es könnte bei Leuten, die wegen technischem Stress einen echten Zusammenbruch erlebt haben, einen falschen Eindruck erwecken
Bei mir gab es das genau einmal, und es war eine Angstattacke. Ich hatte großes Glück, dass meine Frau neben mir war, mir die Situation erklärte und mir half zu verstehen, was ich durchmachte. Sie hatte das schon mehrfach erlebt, für mich war es das erste und glücklicherweise letzte Mal
So etwas kann Menschen passieren, und daran ist an sich nichts falsch. Es ist sehr wichtig, wirklich zu verinnerlichen, dass das nicht bedeutet, dass man defekt oder schwach ist
Bei mir war es am Ende Xanax, das mich zum Stillstand brachte, und weil ich dadurch einschlafen konnte, halte ich es für sinnvoll, etwas davon griffbereit zu haben
Ich will sagen, dass intrusive Gedanken etwas anderes sind als ein Zustand wie eine Angst- oder Panikattacke, den man tatsächlich nicht kontrollieren kann und der einen funktional lähmt. Wenn so etwas passiert, kann man nicht arbeiten, und das ist auch in Ordnung
Nicht jeder Zusammenbruch äußert sich als Panik- oder Angstattacke. So kann er sich zeigen, aber das ist nicht die einzige Form. Stress wirkt sich von Person zu Person und sogar je nach Stressor sehr unterschiedlich aus
Man kann von außen kaum „diagnostizieren“, was genau im Kopf dieser Person passiert ist. Selbst wenn es keine voll ausgeprägte Panikattacke war, klingt es doch so, als sei sie für einige Stunden funktional gelähmt gewesen
Wenn man online nachschaut, sieht es so aus, als könne Xanax abhängig machen
https://www.drugs.com/xanax.html
Es scheint nichts zu sein, das man leichtfertig einnehmen sollte
Wahrscheinlich werden wir zusehen, wie die große Gruppe von Menschen, die Mitte der 2000er in die Tech-Branche eingestiegen ist, an stressbedingten Erkrankungen zugrunde geht
Als jemand, der das ganze Leben mit starker Angst gelebt hat, ist schon der Gedanke beängstigend, dass eine einzige abhängig machende Pille all das verschwinden lassen könnte. Ich hätte das Gefühl, mein Leben lang daran zu hängen
Der Stress dieser Person wurde durch eine einzige Zeile Code von PostHog verursacht. Der zurückgesetzte Commit ist dieser hier: https://github.com/PostHog/posthog-js/pull/1371/commits/7598...
Daraus lassen sich zwei Lehren ziehen. Erstens: Wenn man es ausrollt, besitzt man es auch. Deshalb ist weniger auszurollen besser, und Abhängigkeiten sollten minimiert werden. Zweitens sollte Unwichtiges außerhalb des kritischen Pfads liegen. Der Motor darf nicht stehen bleiben, nur weil der Kompressor der Klimaanlage kaputt ist. Im Browser ist das sehr schwer zu erreichen, aber den Versuch ist es wert
Noch schlimmer: Es wirkt, als würde PostHog Teile seines eigenen Codes zur Laufzeit dynamisch aktualisieren, statt alles beim Build zu bündeln.
In der Dokumentation gibt es eine erweiterte Option, alle Abhängigkeiten in den Build aufzunehmen. Ich verstehe, warum man das so macht, und vielleicht missverstehe ich etwas, aber aus Nutzersicht würde ich erwarten, dass Lazy Loading von Laufzeitcode eine Optimierungsoption ist und nicht der Standard. Meiner Meinung nach sollte man das nur einsetzen, wenn ein vollständiges Bundle zu ernsthaften Auslieferungsverzögerungen führt.
Der Bug steckte offenbar in einem monkey-gepatchten
window.fetch.https://github.com/PostHog/posthog-js/blob/759829c67fcb8720f...
Die wichtigste Lehre hier ist: Wenn man eine populäre Library baut und globale Funktionen monkey-patcht, dann muss das wirklich hervorragend getestet sein.
„Lass uns PostHog-Aufrufe sicherheitshalber in try/catch packen“ und „Wegen PostHog können wir buchstäblich keine POST-Requests mit
fetch()senden“ sind zwei völlig verschiedene Dinge.fetchzu liegen als auch an übermäßigem Mocking: https://github.com/PostHog/posthog-js/blob/main/src/_tests...Da die kompletten
fetch- und XHR-Funktionen gemockt werden und dann nichts tun, ist es natürlich nicht möglich, Probleme zu entdecken, die bei der Interaktion mit der nativen Implementierung oder anderen Libraries darunter entstehen. Cypress ist auch eingerichtet, daher verstehe ich nicht, warum man Browser-APIs mocken will.Bei einer vernünftigen Integration sollte im schlimmsten Fall nur die Verarbeitung von Monitoring-Events fehlschlagen.
Dass PostHog eine sehr wichtige globale Funktion patcht, sollte eine gut dokumentierte Eigenschaft sein. Dann wissen die Nutzer davon und können es beim Debuggen von Problemen, die nach außen hin schwer erklärbar sind, sinnvollerweise in Betracht ziehen.
Heap Analytics macht zum Beispiel immer noch, Stand dieses Monats, irgendetwas mit Hotwire intern, wodurch Hotwire zufällig komplett kaputtgeht und jeder Klick zu einem vollständigen Seiten-Reload wird. Nach meiner Erfahrung betrifft das 30 bis 60 % der Seitenladungen. Es lässt sich beheben, aber ich musste mehr als 50 Stunden debuggen, bis Heap erst nach dem gesamten Hotwire-JavaScript geladen wurde.
Wie andere schon gesagt haben, war der Bug, der zu diesem nächtlichen Stress führte, eine Ein-Zeilen-Änderung in der PostHog-Library[0].
Für mich ist das eine Erinnerung daran, wie wichtig es ist, Variablen präzise zu benennen.
Der Code
res = await originalFetch(url, init)wirkt harmlos genug. Aber wie die TypeScript-Deklaration zeigt, ist der Parameterurlnicht zwingend eine URL:url: URL | RequestInfoWenn es kein URL-, sondern ein RequestInfo-Objekt ist, entsteht das Problem. Denn weiter oben in der Funktionsimplementierung wurde bereits ein Request-Objekt erstellt und damit schon „verbraucht“, sodass es hier nicht noch einmal verwendet werden kann.
Hätte der Parameter einen präziseren Namen wie
urlOrRequestInfogehabt, wäre es bei dieser Änderung schwerer gewesen, das Problem zu übersehen.Das ist deutlich spekulativer, aber mit linearen Typen aus der linearen Logik könnte man formalisieren, dass ein Wert „verbraucht“ wird; ein geeignetes Typsystem könnte diese Art von Bug also vielleicht verhindern.
[0] https://github.com/PostHog/posthog-js/pull/1351/commits/2497...
Man muss sich nur die Ownership-Semantik von Sprachen wie Rust ansehen. Unüberwindbar ist sie nicht, und mit Erfahrung wird es vor allem leichter, aber sie ist belastend genug, dass Lernende sich am häufigsten genau darüber beschweren.
Es war ein stressiger, aber auch lustiger Artikel. Der selbstanklagende Teil kam mir allerdings allzu bekannt vor.
Ich betreibe eine recht erfolgreiche iOS/macOS-App und habe einmal einen Release ausgeliefert, der mehr als 350.000 Installationen komplett kaputtgemacht hat. Es war nicht ausschließlich meine Schuld, aber es war mein Produkt, also machte das kaum einen Unterschied.
Der kalte Schweiß und die Scham damals waren wirklich heftig. Und weil es der App Store war, musste auch der Fix wieder durch den Review-Prozess, was alles verzögerte. Zum Glück ging die Prüfung 30 Minuten nach dem Einreichen los, und wenige Minuten später war es genehmigt.
Mit wachsender Erfahrung und dem Wechsel in Führungsrollen wurde mir klar, dass das extrem wertvoll war. Vielleicht hätte es mich früher gestresst, aber inzwischen ist die Erinnerung so weit weg, dass ich sie kaum noch erreiche. Jetzt stresst es mich definitiv nicht mehr.
Das mag umstritten sein, aber ich lasse manchmal Leute in frühen Karrierephasen Produktionsumgebungen kaputtmachen. Nämlich dann, wenn es absehbar ist und ich sicher bin, dass wir schnell wiederherstellen können.
Dass Menschen Raum zum Scheitern brauchen, ist selbstverständlich, aber viele Führungskräfte ziehen die Grenze bei Fehlern, die echte Kunden betreffen. Wenn man nicht gerade etwas Kritisches wie Software zum Landen von Flugzeugen baut — was zum Glück sehr oft der Fall ist —, dann sollte man das Team auch Betriebsstörungen erleben lassen, selbst wenn das bedeutet, dass jemand in Spokane, Washington, das Produkt ein paar Minuten lang nicht benutzen kann.
Danke, dass du so einen Beitrag geschrieben hast. Ich lese besonders gern, wie Menschen solche Herausforderungen unter Druck bewältigen, meist mitten in der Nacht.
Nicht nur die technische Nachbetrachtung, sondern auch die menschliche Perspektive, die aus solchen Geschichten normalerweise entfernt wird, macht es aus meiner Sicht besser. Diese Art technischer Erzählung können meist nur kleine Teams, Solo-Entwickler oder Gründer frei teilen.
Schon die Art, wie das Problem verfolgt wurde, zeigt zuerst einmal: Das ist ein Programmierer. Er ging an den eigenen Code und an die Logs. Beides ist vernünftig, und beides kann die Ursache sein, aber der wichtigste Hinweis, den er hatte, nämlich „auf localhost hat es funktioniert“, wurde übersehen
Egal ob SRE, DevOps, Plattformingenieur oder welcher Titel an dem Tag gerade dranhängt: Ich hätte mich auf die Unterschiede zwischen dem funktionierenden und dem nicht funktionierenden System konzentriert. Ich hätte Unterschiede einzeln hinzugefügt und wieder entfernt oder entfernt und wieder hinzugefügt, bis irgendetwas funktioniert
Ich sehe dabei zwei Dinge. 1) Es gibt eine funktionierende Umgebung. 2) Die fehlschlagende Umgebung hat ursprünglich ebenfalls funktioniert und erst dann begonnen zu versagen
Das soll nicht heißen, dass meine Methode überlegen ist. Ich will nur den Unterschied in der Art zeigen, wie man ein Problem betrachtet. Beide engen es entlang dessen ein, was sie kennen. Ich kenne Systeme, und du kennst Code
Ich hielt das für aussichtslos, aber ein älterer und klügerer Techniker brachte mir die Methode bei
Ein gutes Board wurde auf einen Extender gesteckt, und ein fehlschlagendes Diagnoseprogramm lief in einer Schleife. Mit dem Oszilloskop wurden alle Pins am Stecker betrachtet und dokumentiert. Dann wurde auf ein schlechtes Board gewechselt und das Ganze wiederholt
Welches Signal ist anders? Diesem Signal folgt man zurück. Wenn der Schaltplan nicht passt, zeichnet man mit Voltmeter und Augen einen Schaltplan, der die tatsächliche Verdrahtung widerspiegelt
Er nannte das „gute Karte - schlechte Karte“, und es hat tatsächlich funktioniert. Ich würde nicht behaupten, dass es kosteneffizient war, aber wir haben alle Boards repariert, und meine Fähigkeit zur Fehlersuche in digitalen Elektronikschaltungen ist stark gewachsen
Es war eine Art „Feuerwehr“-Arbeit. Man wartete darauf, dass das System ausfiel, deshalb war es egal, wenn zwei Techniker eine Woche an einem einzelnen Board saßen
„Gehen wir auf die Version von vor einem Monat zurück. Geht nicht. Vor drei Monaten? Geht nicht. Scheitert immer noch. Vor einem Jahr? Geht überhaupt nicht.“
Wurde nur der eigene Code zurückgesetzt, während das PostHog-Update, das am selben Tag alles kaputtgemacht hat, weiterverwendet wurde? Meine Lehre daraus ist, dass man alles zurückrollen können muss, einschließlich der Abhängigkeiten
https://github.com/PostHog/posthog/issues/24471#issuecomment...
Es gibt auch die Möglichkeit, direkt selbst zu bundlen
https://github.com/PostHog/posthog/issues/24471#issuecomment...
Der Autor des Originalbeitrags hat das gut gehandhabt. Das Positive an solchen Ausfällen ist, dass eine Menge wertvoller Lektionen daraus hervorgehen
Ein guter Text, der wieder daran erinnert, dass hinter einem Dienst Menschen stehen, und der den Debugging-Prozess gut zeigt
Realistisch betrachtet sorgt Druck nicht dafür, dass man ein Problem schneller debuggt. Meist behindert er das Denken. Man sollte das Ergebnis so weit wie möglich ausblenden und so ruhig wie möglich bleiben
Die meisten von uns haben so eine Situation wohl schon erlebt, wenn auch in unterschiedlichem Ausmaß. Natürlich ist der Stress, das eigene Unternehmen zu führen, noch einmal besonders groß