StartseiteArtikel

Führungskräfte ohne Programmiererfahrung haben mit Claude Code innerhalb von zwei Tagen ein neues Programm in Betrieb genommen. Als die Ingenieure es übernahmen, stellten sie fest: Ein einziger Fehler führte dazu, dass die KI an einem Tag die Serverkosten eines ganzen Monats verbraucht hat.

CSDN2026-07-01 11:07
Wachsamkeit vor "atmosphärischem Codieren"

Als erfahrener Cloud-Infrastruktur-Ingenieur hat Jumpei Ueno kürzlich ein Projekt übernommen, das von "Stimmungs-Coding" zurückgelassen wurde.

Der Entwickler dieses Projekts war kein professioneller Ingenieur, sondern der CFO (Chef Finanzoffizier) des Unternehmens. Mit Hilfe von Claude Code hat er in nur zwei Tagen die Entwicklung eines SaaS-Produkts abgeschlossen und es online gestellt. Anschließend hat er die anschließende Wartung an Jumpei Ueno übergeben.

Für Jumpei Ueno ist eine solche Situation nichts Ungewöhnliches. Menschen ohne Ingenieurshintergrund bauen schnell Produkte, und die Ingenieure, die für die langfristige Wartung zuständig sind, ordnen dann das Backend-System Stück für Stück. Doch jedes Mal, wenn er genauer untersucht, findet er neue und unterschiedliche Probleme.

Was ihn diesmal am meisten überraschte, war weder die chaotische Schlüsselverwaltung noch das Fehlen von Tests im gesamten Projekt, sondern dass die Kosten für die Cloud-Dienste außer Kontrolle geraten waren und tatsächlich Geld wie Wasser floss.

Dafür hat Jumpei Ueno den gesamten Untersuchungsprozess vollständig dokumentiert, um Menschen, die mit "Stimmungs-Coding" Produkte entwickeln, eine Warnung zu geben.

CFO: Ich weiß nicht mehr, was ich gemacht habe

Alles begann an einem Tag, als Jumpei Ueno die Kostenübersicht der LLM-API studierte und bemerkte, dass die Ausgaben an einem Tag auffällig hoch waren. Während die Kosten an anderen Tagen fast am unteren Ende lagen, stieg sie an diesem Tag in die Höhe und nahm fast die Hälfte der monatlichen API-Kosten ein.

Als er diese Zahl sah, gestand Jumpei Ueno, dass er "schlichtweg geschockt" war.

Der Grund ist einfach: Die AI-Aufrufkosten an diesem einen Tag überstiegen die Betriebskosten der gesamten Server-Cluster für einen Monat. Mit anderen Worten, es war billiger, alle Server einen Monat lang laufen zu lassen, als die AI einen Tag lang arbeiten zu lassen. Dies war ihm zunächst unverständlich, wie solche Kosten entstehen konnten.

Also suchte er den CFO auf, der ursprünglich dieses System entwickelt hatte, und stellte ihm eine direkte Frage: "Was hast du an diesem Tag genau gemacht?"

Die Antwort des anderen war nur: "Ehrlich gesagt, ich weiß nicht mehr, was ich an diesem Tag gemacht habe."

Diese Antwort ließ einen lachen und weinen zugleich.

Jumpei Ueno meint jedoch, dass dies nicht der Zeitpunkt ist, um die Schuld zu suchen (zumindest nicht vollständig). Je tiefer er die Untersuchung vorantrieb, desto stärker wurde ihm bewusst, dass es ganz normal war, dass der andere sich nicht mehr erinnern konnte. Das eigentliche "Geldfressen" war nicht die Aktion einer Person, sondern das Wiederholungsmechanismus hinter dem System.

Untersuchung beginnt: Zunächst dachte er, es sei eine menschliche Wiederholung von Aufrufen

Am Anfang dachte Jumpei Ueno ganz einfach: "Du hast an einem Tag so viele Funktionen entwickelt und ständig in der Produktionsumgebung getestet. Bei jedem Test wird die teure API des großen Modells aufgerufen. Allmählich summieren sich die Kosten, und schließlich explodiert die Rechnung."

Diese Vermutung schien auch vernünftig. Nachdem die Commit-Einträge an diesem Tag von morgens bis abends fast nicht aufgehört hatten, und es rund um die AI-Generierungsfunktion mehr als zwanzig Commits gab. Es schien also plausibel, die hohen Kosten auf die wiederholten Tests während der Entwicklung zurückzuführen.

Aber als sie tatsächlich die Anwendungslogs - einschließlich der Aufgabenwarteschlange, der Datenbank und der Anforderungsaufzeichnungen - untersuchten, stellten sie fest, dass die Realität ganz anders war.

Dies war nicht das "langsame Geldfressen", das sich aus wiederholten manuellen Aktionen summierte, sondern dass die gleichen hochkostspieligen Aufgaben von der Maschine immer wieder vollständig ausgeführt wurden. Für denselben Mandanten wurde eine Aufgabe, die normalerweise nur einmal ausgeführt wird, 21 Mal ausgeführt.

Ein Mensch würde nicht 21 Mal den gleichen Knopf in einem Tag drücken.

Das eigentliche "Drücken des Knopfs" wiederholt wurde nicht von einem Menschen, sondern von einem Programm.

Das Schrecklichste ist: Die Aufgabe war erfolgreich, scheiterte aber am letzten Schritt

Nach Ansicht von Jumpei Ueno ist dies der Kern der ganzen Geschichte.

Diese Batch-Aufgabe ruft nacheinander mehrere große Modelle auf und schreibt die zurückgegebenen Ergebnisse in die Datenbank. Der Gesamtablauf ist grob wie folgt:

Zunächst werden eine Reihe von Anforderungen an mehrere LLMs gestellt - dies ist auch der Hauptteil, in dem die Kosten entstehen;

Anschließend werden die vom Modell zurückgegebenen Ergebnisse in die Datenbank geschrieben.

Das eigentliche Problem tritt genau im zweiten Schritt auf.

Beim Schreiben in die Datenbank referenzierte das Programm ein Feld, das eigentlich bereits hinzugefügt werden sollte. Doch in der Datenbank der Produktionsumgebung war die Migration noch nicht abgeschlossen, und dieses Feld existierte tatsächlich nicht. Daher warf die Datenbank direkt einen "column does not exist"-Fehler, und die gesamte Aufgabe endete schließlich mit einem 500-Fehler.

Viele Leute denken bei "Aufgabe fehlgeschlagen" zunächst: "Der Modellaufruf ist fehlgeschlagen, das Geld ist vergeudet."

Aber das stimmt nicht.

Alle LLM-Anforderungen wurden erfolgreich mit dem Statuscode 200 zurückgegeben, was bedeutet, dass jeder Aufruf bereits abgerechnet wurde. Das Modell hat die Inferenz durchgeführt und die Ergebnisse zurückgegeben, nur beim letzten Schritt, dem Schreiben in die Datenbank, ist ein Problem aufgetreten, und die gesamte Aufgabe ist fehlgeschlagen.

Jumpei Ueno hat eine bildliche Metapher verwendet:

Es ist wie in einem Restaurant, wo man ein komplettes Menü gegessen und bezahlt hat. Gerade als man aufstehen will und sagt: "Danke für das Essen", stürzt man plötzlich und verliert das Gedächtnis. Wenn man aufwacht, ist man wieder am Tisch und denkt, man hat noch nicht gegessen, also bestellt man wieder ein komplettes Menü. So geht es 21 Mal im Kreis.

Das gegessene Essen verschwindet nicht, genauso wie die bereits abgerechneten Aufrufe des großen Modells nicht storniert werden können; aber bei jeder Wiederholung beginnt das System von vorne.

Es gibt in der Branche einen Begriff: "Retry Storm (Wiederholungssturm)". Normalerweise versteht man darunter, dass die Anforderungen ständig fehlschlagen, und das System wiederholt die Versuche immer wieder. Aber diesmal war die Situation völlig anders.

Tatsächlich ist passiert: Jeder Aufruf war tatsächlich erfolgreich, nur wurden die erfolgreichen Ergebnisse im letzten Schritt "verworfen", und das System startete dann eine ganze neue Runde von Aufrufen.

Nach Ansicht von Jumpei Ueno ist dies das am wenigsten intuitiv und am schrecklichsten an der ganzen Sache.

Zwei Probleme zusammenführten schließlich dazu, dass die Aufgabe 21 Mal wiederholt wurde

Nach weiterer Untersuchung stellte Jumpei Ueno fest, dass das System die gleichen Aufgaben immer wieder ausführte, weil zwei Probleme zusammenwirkten.

Das erste Problem war ein Fehler in der Deploy-Reihenfolge.

Der Code wurde zunächst in die Produktionsumgebung deployed und ging davon aus, dass das neue Feld in der Datenbank bereits existiert; jedoch wurde die Datenbankmigration, die für das Hinzufügen dieses Felds verantwortlich war, noch nicht durchgeführt. Das heißt, der Code wurde zuerst online gestellt, und die Datenbankstruktur wurde später aktualisiert. Infolgedessen greift das Programm jedes Mal auf ein Feld zu, das gar nicht existiert, und gibt somit ständig Fehler aus.

Jumpei Ueno betont besonders, dass dies ein deterministischer Fehler ist - egal wie oft man es wiederholt, es kann sich nicht von selbst beheben.

Das zweite Problem stammt aus dem automatischen Wiederholungsmechanismus der Aufgabenwarteschlange.

Bei einer verwalteten Aufgabenwarteschlange geht man davon aus, wenn eine Aufgabe mit einem 500-Fehler endet, dass es sich um einen temporären Fehler handelt, und führt die Aufgabe automatisch erneut aus. Dieser Mechanismus wurde ursprünglich entwickelt, um mit zufälligen Problemen wie Netzwerkstörungen umzugehen, und ist an sich nicht falsch.

Aber diesmal war das Problem kein Netzwerkfehler, sondern dass das entsprechende Feld in der Datenbank einfach nicht existierte. Das Feld wird nicht einfach durch wiederholte Versuche erscheinen, aber die Aufgabenwarteschlange führt dennoch "freundlicherweise" immer wieder die gleiche Aufgabe aus. Was noch schlimmer ist, ist, dass diese Batch-Aufgabe selbst nicht idempotent ist.

Das heißt, es überprüft nicht, welche Arbeit bereits erledigt ist, sondern beginnt bei jeder Wiederholung von vorne. Daher wird bei jeder Wiederholung alle LLMs erneut aufgerufen, und es entstehen erneut eine ganze Runde voller API-Kosten.

Deterministischer Fehler + Automatische Wiederholung + Nicht-idempotentes Design. Jumpei Ueno sagt, wenn diese drei Faktoren zusammenkommen, fließt das Geld stumm und stille fort.

Deshalb kann der CFO seines Unternehmens sich überhaupt nicht erinnern, was er gemacht hat - denn das eigentliche "Drücken des Knopfs" wiederholt wurde nicht von einem Menschen, sondern von der Aufgabenwarteschlange.

Als er dem CFO den ganzen Grund erklärte, runzelte dieser nur die Stirn und sagte verwirrt: "Äh?"

Jumpei Ueno meint, dass es für Menschen ohne Ingenieurshintergrund tatsächlich schwer ist, sofort zu verstehen, dass "der Modellaufruf erfolgreich war, die Kosten bereits entstanden sind, aber die erfolgreichen Ergebnisse anschließend verworfen werden und der Aufruf erneut durchgeführt wird".

Der Wiederholungsmechanismus ist nicht immer eine Güte

Nach dieser Erfahrung hat Jumpei Ueno einige Erfahrungen zusammengefasst. Er meint, dass diese Lehren nicht nur für ihn selbst, sondern auch für alle Ingenieure gelten, die die Wartung von bereits online gestellten Systemen anderer übernehmen.

Erstens: Ein deterministischer Fehler wird sich nicht von selbst beheben, wenn man ihn immer wieder wiederholt. Ob es sich um eine Inkonsistenz im Datenbank-Schema oder um 4xx-Fehler handelt, die eindeutig auf Probleme im Programm selbst zurückzuführen sind, das Ergebnis wird sich nicht ändern, wie oft man auch wiederholt. Bei solchen Fehlern sollte das System sofort beendet werden, anstatt unendlich zu wiederholen. Gleichzeitig sollte jeder Wiederholungsmechanismus eine klare Obergrenze für die Anzahl der Wiederholungen festlegen. Wiederholung ist kein allmächtiger Schutz.

Zweitens: Je größer die Nebenwirkungen einer Aufgabe sind, desto mehr muss sie idempotent sein. Alle Vorgänge, die echte Kosten verursachen, wie der Aufruf einer abgerechneten API oder einer Schnittstelle für ein großes Modell, sollten von Anfang an die Fähigkeit haben, "bereits abgeschlossene Aufgaben zu überspringen". Andernfalls ist jede Wiederholung nicht einfach ein "erneutes Ausführen", sondern es wird erneut abgerechnet.

Drittens: Die Bereitstellung in der Produktionsumgebung muss der Reihenfolge "Erst Datenbank aktualisieren, dann Code deployen" folgen. Erst nachdem die Datenbankmigration abgeschlossen ist und dann der Code, der von den neuen Feldern abhängt, online gestellt wird, kann man vermeiden, dass in der Zeitspanne zwischen den beiden eine große Anzahl solcher deterministischen Fehler entsteht.

Darüber hinaus erwähnt er auch, dass wenn die Kosten nicht beobachtbar sind, wird man oft erst merken, dass ein Problem aufgetreten ist, wenn das Geld aufgebraucht ist. Dass er dieses Mal die Abweichung bemerken konnte, war nur deshalb möglich, weil er zufällig die API-Kostenkurve angesehen hatte. Wenn man nicht die Produktionsumgebung und die Testumgebung mit unterschiedlichen API-Keys verwendet und keine Überwachungsmechanismen wie Budgetwarnungen hat, wird fast niemand die Abweichung bemerken, bevor man die Monatsrechnung erhält.

Schließlich spricht Jumpei Ueno auch über die Veränderungen, die das "Stimmungs-Coding" mit sich bringt.

Er sagt, dass die KI tatsächlich die Schwelle für Nicht-Ingenieure, Produktionssysteme zu entwickeln, erheblich gesenkt hat und ihnen ermöglicht hat, Produkte in kurzer Zeit zu entwickeln. Aber es ist eine ganz andere Fähigkeit, zu wissen, wie man Funktionen entwickelt, als zu wissen, wie ein System fehlschlagen kann und wie es stumm und stille große Kosten verursachen kann. Und letzteres muss immer noch von den Ingenieuren übernommen werden, die das System später übernehmen.

Wie er zusammengefasst hat:

Zwei Tage reichen aus, um eine Funktion zu entwickeln, aber es ist auf keinen Fall etwas, das man in zwei Tagen lernen kann, um zu vermeiden, dass eine "freundliche automatische Wiederholung" zu einem solchen Zwischenfall wie "Verwerfen der bereits erfolgreichen Ergebnisse und erneute Abrechnung" wird.

Quelle:

https://junueno.dev/en/retry-storm-rebilled-llm-cost/

Dieser Artikel stammt aus dem WeChat-Account "CSDN", Autor: Su Mi. 36Kr hat die Veröffentlichung mit Genehmigung durchgeführt.