Sie haben einen dritten Stapel technischer Schulden. Niemand hat ein Tool gebaut, um ihn zu finden.
Du startest deine gewohnte App. FEHLER. Du bist schon genervt, weil du heute eigentlich keine Wartung geplant hattest. Also gräbst du. Mein Terminal spuckte mir ECONNREFUSED 127.0.0.1:46279 ins Gesicht und es dauerte exakt dreißig Sekunden bis ich kapierte, dass sich niemand, nirgendwo, darum kümmern würde. Keine Status-Seite. Kein Ticket zum Erstellen. Keine SLA zum Wedeln. Der kostenlose Service, von dem ein Teil meiner Pipeline abhing, war einfach down, und der einzige Mensch auf der Erde, den das interessierte, war ich.
Natürlich hatte ich nie einen Vertrag mit denen unterschrieben. Ich nutzte einen kostenlosen Service. Ich tauchte nie in deren Dashboards auf. Und trotzdem schuldeten sie mir an diesem Montagmorgen um 9:17 Uhr etwas, wovon sie nicht mal wussten, dass sie es mir schuldeten. Oder eigentlich andersrum: Ich schuldete ihnen. Ich hatte monatelang Schulden angehäuft, ohne es zu merken, und der Gläubiger hatte gerade kassiert.
TLDR (Du kennst die Technical Debt, die du geschrieben hast. Du misst die Technical Debt, die du von deinen Dependencies geerbt hast. Es gibt einen dritten Haufen, über den niemand redet: die Schulden, die du importierst, jedes Mal wenn du eine kostenlose SaaS in deine Pipeline einbaust. Taucht in keinem Dashboard auf. Kein Linter erwischt sie. Dependabot sieht sie nicht. Prüfe deine importierten Schulden, bevor ein Montagmorgen sie für dich prüft.)

Die drei Haufen
Es gibt drei Arten von Technical Debt und die meisten Teams zählen nur zwei davon.
Der erste ist die Debt, die du geschrieben hast. Der Freitagnachmittag-Hack, der überlebt hat. Das TODO von 2022, das tragend wurde. Das if-Statement, das temporär sein sollte und jetzt seine eigene Commit-History hat. Du weißt, dass es existiert, weil du es geschrieben hast, und du weißt ungefähr, wo es lebt, weil der schlechte Geruch dir folgt. Dein Linter erwischt einen Teil davon. Code Review erwischt einen anderen Teil. Der Rest sitzt in deinem Kopf.
Der zweite Haufen ist die Debt, die du geerbt hast. Lockfiles voller transitiver Dependencies, die du nie ausgewählt hast. Libraries, die seit drei Jahren nicht mehr shipped haben, aber sich immer noch installieren. Packages mit zwei Maintainern und einer davon ist gerade auf einen Bauernhof gezogen. Du weißt, dass dieser Haufen auch existiert, weil es Tools dafür gibt. npm audit, Dependabot, Snyk, Renovate. Sie schreien dich jeden Montagmorgen an, ob du willst oder nicht. Das Geschrei ist nervig, aber wenigstens schreit jemand.
Dann gibt es den dritten Haufen. Den Haufen, für den du keinen Namen hast, weil ihn niemand benannt hat. Der kostenlose Service, den du in einen Schritt deiner Pipeline steckst, weil es einfacher war, als das Ding selbst zu bauen. Die gehostete API, die ein Stück deiner Daten verarbeitet, weil sie ein großzügiges Free Tier hatte. Der Webhook-Endpoint, der eine Konvertierung macht, die du nie selbst geschrieben hättest. Nichts von dieser Debt ist in deiner Codebase. Nichts davon taucht in der package.json auf. Kein Tool überwacht es. Du zählst es nicht mal als Dependency in deinem eigenen Kopf, weil Dependencies Dinge sind, die du importierst, und diese Dinge sind Dinge, die du aufrufst.
Aber sie sind Dependencies. Und sie sind Debt. Die Debt sitzt nur woanders, auf jemand anderes Server, mit jemand anderes Anreizen. Du hast sie nicht ausgegeben. Du hast sie importiert.
Die Debt, die du nicht ausgegeben hast, ist trotzdem deine Debt, in dem Moment, wo sie fällt.
Warum niemand sie sieht
Der Grund, warum niemand diesen dritten Haufen sieht, ist strukturell, nicht dumm.
Jedes Tool, das wir zum Messen von Technical Debt gebaut haben, schaut in deine Codebase. Linter parsen deine Dateien. Dependabot liest deine Manifeste. Snyk scannt deine Lockfile. Code Review passiert bei deinen PRs. Der ganze Observability-Stack nimmt an, dass die Debt in Artefakten lebt, die du besitzt und greppen kannst. Importierte Debt lebt nicht in Artefakten, die du besitzt. Sie lebt unter einer URL. Und eine URL ist kein Asset, sondern ein Versprechen.
Ein Versprechen von einer Entität, die dir nichts schuldet.
Es gibt auch einen weicheren Grund. Du hast diese Dinge nicht absichtlich importiert. Du hast sie an einem Dienstagnachmittag importiert, als du eine schnelle Konvertierung brauchtest, gegoogelt hast, einen kostenlosen Endpoint gefunden, die URL in eine Config-Datei eingefügt und weitergemacht hast. Es fühlte sich an wie ein Tool zu benutzen, nicht wie einen Vertrag zu unterschreiben. Nichts in deinem Editor sagte dir, dass du gerade die Sterblichkeit eines Fremden an deine Pipeline geschraubt hattest. Also hast du kein mentales Hauptbuch aktualisiert. Es gab kein Hauptbuch.
Das Lustige ist, dass der Rest der Branche sich durchaus bewusst ist, dass dieses Zeug kaputtgeht. Eine 2025er Umfrage unter 1.000 Senior Tech Executives fand heraus, dass 93% sich wegen Downtime-Impact sorgen und 100% outage-bedingte Umsatzverluste in dem Jahr erlebt haben. Die Liste öffentlicher Incidents liest sich wie ein Horror-Katalog: AWS us-east-1 geht stundenlang down und reißt abhängige SaaS-Provider mit, Cloudflare WAF-Regeln löschen einen Chunk des globalen Traffics mit einem einzigen Push, Azure-Konfigurationsfehler nehmen Microsoft 365 und Xbox gleichzeitig mit. Wir wissen, dass Outages passieren. Wir tracken sie öffentlich. Wir schreiben Postmortems.
Aber wir tracken sie danach. Es gibt kein Tool, das in dein Repo marschiert und sagt "du hängst von einer Handvoll Dingen ab, die morgen verschwinden könnten und du hast für null davon einen Plan." Dieses Tool existiert nicht, weil die Inputs nicht in deinem Repo sind. Sie sind über HTTP-Calls in zufälligen Dateien verstreut, hardcodierte URLs in Configs, fetch-Statements vergraben in Service-Modulen, env vars die auf Hostnamen zeigen, die du einmal aufgeschrieben und vergessen hast.
Du weißt, wie deine package.json aussieht. Du hast keine Ahnung, wie deine outbound calls aussehen. Das ist die Lücke.
Das Audit, das niemand fährt
Nachdem Krokis Excalidraw-Backend crashte und sich weigerte zurückzukommen, setzte ich mich zum ersten Mal seit Jahren hin und führte das Audit durch. Nicht das für npm-Packages. Das für ausgehende HTTP-Calls zu kostenlosen Services, für die ich nie bezahlt hatte und die ich nicht schnell ersetzen konnte.
Es kostete mich einen Samstagmorgen, alles zu durchsuchen. Die Pipeline, an der ich damals arbeitete, war eine Produktkatalog-Automatisierung für einen kleinen E-Commerce-Kunden, die Art von Ding, die Montage-Diagramme und visuelle Specs für Produktseiten in deren Shop generiert. Nicht glamourös, aber es shipped jeden Tag. Und jeder Schritt der Pipeline hatte irgendwo eine kostenlose SaaS drangeschraubt.
Ich kam auf 14 ausgehende Calls zu Services, für die ich nie bezahlt hatte. Ich will dich nicht mit dem kompletten Inventar langweilen. Die interessanten Zahlen waren woanders. Die Anzahl der Items, die irgendwo einen dokumentierten Fallback-Plan hatten: null. Die Anzahl der Items mit Monitoring auf dem Upstream-Service: null. Die Anzahl der Items, die ich jemals stress-getestet hatte, indem ich die Dependency absichtlich killte: auch null.
Ich betrieb eine Produktions-Pipeline auf einem Stack kostenloser Versprechen, und ich hatte das so lange gemacht, dass es nicht mal mehr als Risiko registrierte. Es registrierte als "Infrastruktur."
Der Kroki-Ersatz, der eigentliche Fix, war klein. Eine einzige TypeScript-Datei, die exakt das macht, was der kaputte Service für mich gemacht hatte, nicht mehr, nicht weniger. Läuft auf Bun. Ruft eine Library direkt auf, anstatt durch einen headless Browser zu gehen. Lebt in 47 Zeilen. Nutzt 93MB RAM. Rendert ein Diagramm in etwa 2 Millisekunden. Es läuft in einem Docker-Container auf einem VPS, für den ich schon 6 Dollar im Monat zahlte, im selben internen Netzwerk wie der Rest des Stacks. Kein öffentlicher Endpoint. Keine Zertifikate. Keine Angriffsfläche. Es läuft seit dem Tag, an dem ich es geschrieben habe, und es ist nicht ein einziges Mal down gewesen.
Nun, der Teil, der mich stört, ist neu. Vor fünf Jahren hätte mich dieser Fix einen ganzen Tag gekostet. Vielleicht zwei. Die Kosten-Nutzen-Rechnung für das Ersetzen einer kostenlosen Dependency wäre für jede einzelne davon ein Nettoverlust gewesen, also hätte ich das gemacht, was alle machen: warten, dass der Upstream zurückkommt und beten. Heute, mit Claude Code vor mir, kostete derselbe Fix dreißig Minuten und ich machte es in einer Kaffeepause. Die Mathematik hat sich gedreht. Das Ding, das früher zu teuer zum Fixen war, ist jetzt zu billig zum Ignorieren.
Genauso wie ich ein bezahltes Setup rebuildte, das der Vendor beschloss auf mir zu retiren, für einen Bruchteil der Kosten vor ein paar Monaten. Die Arbitrage hat sich unter unseren Füßen geändert, und die meisten von uns fahren immer noch die alten Preise im Kopf.
Jede importierte Debt, die ich jahrelang getragen hatte, war plötzlich billig zu refinanzieren. Ich hatte es nur nicht bemerkt.
Der Fix ist nicht Self-Hosting
Vorsicht hier, weil die einfache Version dieser Geschichte "self-hoste alles" ist und das ist die falsche Schlussfolgerung.
Self-Hosting hat seine eigene Debt. Server brauchen Patches. Container brauchen Neustarts. Festplatten laufen voll. Die Tatsache, dass ich eine kostenlose Dependency durch 47 Zeilen meines eigenen Codes ersetzt habe, bedeutet nicht, dass ich das Spiel gewonnen habe. Es bedeutet, dass ich einen Gläubiger gegen einen anderen getauscht habe. Der neue Gläubiger bin ich, und wenigstens weiß ich, wo ich mich finde.
Der eigentliche Fix ist viel langweiliger. Der eigentliche Fix ist eine Bilanz zu führen.
Du brauchst kein Tool. Du brauchst eine Liste. Eine flache Textdatei in deinem Repo, oder einen Abschnitt in deiner README, oder was auch immer deine eigene Faulheit überlebt. Jeden externen Service, den deine Pipeline aufruft. Drei Spalten. Was es macht, was stirbt wenn es stirbt, und was du an einem Montagmorgen dagegen tun würdest. Das ist alles. Der Akt des Schreibens zwingt dich, jede Zeile anzuschauen und die einzige Frage zu stellen, die zählt: habe ich einen Plan, oder setze ich darauf, dass dieser hier zu groß zum Fallen ist?
Die meisten von deinen werden keinen Plan haben. Das ist okay. Der Punkt des Audits ist nicht, alles an einem Wochenende zu fixen, sondern den dritten Haufen sichtbar zu machen. Sobald du ihn sehen kannst, kannst du anfangen, die billigsten Items zuerst zu refinanzieren. Die Zwei-Millisekunden-Ersetzungen. Die 47-Zeilen-Fixes. Die, wo die Library als Package existiert und das einzige, wofür du je bezahlt hast, war der HTTP-Wrapper.
Du wirst entdecken, wie ich, dass eine überraschende Anzahl deiner importierten Debts genau das sind: ein HTTP-Wrapper um etwas, das du direkt hättest aufrufen können. Die Infrastruktur sah beeindruckend aus, weil es ein gehostetes Dashboard und eine Status-Seite und eine Marke gab. Entferne den Wrapper und die eigentliche Logik sind fünfzig Zeilen. Das ist dasselbe Muster, auf das ich auch anderswo immer wieder stoße, und deshalb habe ich ein ganzes Stück darüber geschrieben, wie das billigste Tool, das den Job macht, dazu neigt, das schicke in der Produktion zu schlagen. Weniger Oberfläche, weniger zum Kaputtgehen, weniger wovon abhängen.
Drei Fragen für die Bilanz, für jede Zeile.
Erste Frage: wenn dieses Ding an einem Montagmorgen um 9 Uhr stirbt, was funktioniert nicht mehr? Sei ehrlich. Sag nicht "nichts Kritisches." Geh es durch. Verfolge den Call. Schau, wo er landet. Wenn die Antwort "der Publish-Schritt" oder "das kundenorientierte Ding" oder "der Teil, der Geld macht" ist, kreise die Zeile rot ein.
Zweite Frage: habe ich einen Fallback, oder glaube ich nur, dass dieser hier zu groß zum Fallen ist? Das "zu groß zum Fallen"-Reasoning ist genau das Reasoning, das dich umbringt. Cloudflare ist zu groß zum Fallen. AWS us-east-1 ist zu groß zum Fallen. Beide sind 2025 gefallen. Free Tiers von Indie-Maintainern fallen jede Woche. Glaube ist kein Fallback.
Dritte Frage ist die billige. Wie viele Zeilen Code würde es kosten, das selbst zu rebuilden, jetzt gerade, während ich ruhig bin, anstatt in Panik um 9:17 an einem Montag? Vielleicht ist die Antwort "Tausende" und du entscheidest, mit dem Risiko zu leben. Das ist eine echte Entscheidung. Vielleicht ist die Antwort "47" und du machst es während einer Kaffeepause. Das ist auch eine echte Entscheidung. Der Punkt ist, die Entscheidung zu treffen, anstatt sie für dich treffen zu lassen.
Die meisten von uns haben die Entscheidung nie getroffen. Wir haben einfach weiter den kostenlosen Service in die Pipeline geklickt, weil er da war.
Drei Tage nach dem Incident ging ich zurück zu Krokis Status-Seite. Das Excalidraw-Backend war immer noch als down gelistet. Jemand hatte eine Nachricht in deren Discord gepostet und gefragt, ob jemand daran arbeitet. Niemand hatte geantwortet.
Meine Pipeline lief seit 72 Stunden ohne Unterbrechung. Ich hatte vergessen, dass ich jemandem etwas schuldete.
AI macht dich resilient oder egoistisch. Kommt drauf an, wie du schielst. 🤷
Wie auch immer, der Punkt ist: prüfe deine importierten Schulden. Nicht weil du alles fixen musst, sondern weil du es sehen musst. Die Debt, die du sehen kannst, kannst du planen. Die Debt, die du nicht sehen kannst, wartet nur auf einen Montagmorgen.
Quellen
- Cockroach Labs, Outages Observer: Why 2025 Failures Demand Unbreakable Systems in 2026 (https://www.cockroachlabs.com/blog/2025-top-outages/)
(*) Das Cover-Bild wurde von einer AI gemacht, die selbst ein kostenloser Service ist, den ich in meinen Workflow importiere. Mach daraus, was du willst.