28. Juli 2025·6 Min. Lesezeit

EMFILE: zu viele offene Dateien in Node — im Produktivbetrieb debuggen

EMFILE: zu viele offene Dateien in Node treten oft durch geleakte Handles in KI-generierten Apps auf. Häufige Ursachen und schnelle Checks in Produktion, um die Lösung zu bestätigen.

EMFILE: zu viele offene Dateien in Node — im Produktivbetrieb debuggen

Was „zu viele offene Dateien“ wirklich bedeutet

Der Fehler erscheint meist als EMFILE: too many open files (oder ENFILE). Er bedeutet, dass deiner App die Dateideskriptoren ausgegangen sind.

Ein Dateideskriptor ist ein kleines Handle, das das Betriebssystem einem Prozess gibt, wenn er etwas öffnet — eine Datei, einen Netzwerksocket, eine Log-Datei oder ein Verzeichnis. Wenn der Prozess sein Limit erreicht, schlagen neue Opens fehl.

Das kann Teile deiner App kaputtmachen, die gar nicht nach „Dateien“ klingen: API-Aufrufe, Datenbankverbindungen, Uploads, Server-Side-Rendering oder sogar das Einlesen von Konfigurationsdateien. Deshalb kann der gleiche Vorfall wie zufällige 500er aussehen, bis du die echte Meldung in den Logs findest: EMFILE.

Oft tritt das Problem erst nach Stunden oder Tagen auf, weil Lecks langsam sind. Eine Anfrage kann eine Datei oder einen Socket öffnen und vergessen, sie zu schließen. Ein einzelnes Leck ist unsichtbar. Zehntausend Anfragen später ist die nächste Anfrage die, die fehlschlägt.

KI-generierte Node-Apps neigen eher zu Ressourcenlecks, weil sie oft Code-Snippets zusammenkleben, ohne einen klaren Lebenszyklus zu haben. Übliche Hinweise sind fehlende finally-Blöcke, Listener, die bei jeder Anfrage hinzugefügt werden, Stream-Handler ohne Fehlerbehandlung oder „Quick Fixes“, die neue Verbindungen öffnen statt vorhandene wiederzuverwenden.

Wenn es passiert, nimm sofort eine kleine Momentaufnahme. Meist reicht das, um die Spitze einem bestimmten Code und Traffic zuzuordnen:

  • das Zeitfenster (erster Fehler und Peak)
  • welcher Endpoint, Job oder Worker lief
  • Deploy-Version/Commit und alle Konfigurationsänderungen
  • ein vollständiger Stacktrace und nahe Logs
  • Traffic-Level (normal, Spike oder Hintergrundjob)

Wie sich das in Node-Deployments zeigt

EMFILE beginnt selten als saubere, offensichtliche Fehlermeldung. Die meisten Teams bemerken zuerst „zufällige“ 500er, hängende Requests oder einen Container, der plötzlich keine Verbindungen mehr annimmt, obwohl CPU und Speicher normal aussehen.

Zwei Leck-Formen treten im Produktivbetrieb auf:

  • Pro-Request-Lecks schlagen schnell zu. Ein Traffic-Burst führt innerhalb von Minuten zu Fehlern, weil jede Anfrage eine Datei, einen Socket oder einen Watcher offenlässt.
  • Langsame Lecks schlagen spät zu. Die App läuft Stunden oder Tage und fällt dann nach einem stetigen Tropfen von nicht geschlossenen Ressourcen um.

In Logs und Verhalten sieht das oft so aus:

  • Spitzen von 5xx, die nach einem Neustart verschwinden
  • Uploads oder Bildverarbeitung schlagen zuerst fehl (Streams verbrauchen Deskriptoren schnell)
  • Datenbank- oder Redis-Fehler, die erstmal unzusammenhängend wirken (neue Sockets können nicht geöffnet werden)
  • „Lokal funktioniert es“, aber unter echtem Traffic oder Cron-Jobs fehlen Fehler
  • ein Pod ist „verflucht“, während andere normal aussehen

Neustarts können die Ursache verbergen. Wenn deine Plattform abgestürzte Prozesse schnell neu startet, landest du in einer Schleife: das Leck wächst, die App stirbt, die App kommt gesund zurück, und das Leck beginnt erneut.

Autoscaling kann es ebenfalls zufällig erscheinen lassen. Neue Instanzen starten mit sauberer Deskriptor-Anzahl, deshalb verschwinden Fehler, wenn der Traffic verschoben wird. Dann läuft der gleiche Codepfad wieder, und nur einige Pods fallen aus.

Ein letzter Check: Wenn der Fehler sofort beim Start bei geringem Traffic auftritt, triffst du möglicherweise einfach ein niedriges Descriptor-Limit. Wenn er nach Laufzeit auftritt und um bestimmte Routen oder Jobs herum schlimmer wird (Uploads, Scraping, PDF-Generierung), ist es meist ein Anwendungsleck.

Häufige Ursachen in KI-generierten Node-Apps

KI-generierte Node-Projekte laufen oft als Demo, erreichen aber EMFILE, sobald echter Traffic, echte Dateien oder lang laufende Jobs auftauchen. Das zugrundeliegende Muster ist einfach: Etwas öffnet eine Datei oder Verbindung und schließt sie nicht, sodass der Prozess langsam die Dateideskriptoren aufbraucht.

Ein häufiger Auslöser ist Dateihandling mit Streams, die auf einigen Pfaden nicht geschlossen werden. Zum Beispiel öffnet ein Request-Handler einen Read-Stream und beendet früh bei einem Fehler, ohne destroy() aufzurufen oder auf finish/close zu warten.

Ein weiterer häufiger Grund sind „hilfreiche“ Hintergrund-Watcher, die von Scaffold-Vorlagen erstellt werden. Ein Prototyp startet File-Watcher fürs Hot-Reload, Thumbnail-Generierung oder Sync-Aufgaben und läuft dann versehentlich auch in Produktion. Jeder Watcher verbraucht Deskriptoren und kann sich über Worker multiplizieren.

Die Lecks, die am häufigsten auftreten

Diese Kandidaten tauchen in KI-geschriebenem Code immer wieder auf:

  • Streams, die in Schleifen geöffnet werden (CSV-Imports, Batch-Bildverarbeitung) ohne Backpressure, sodass Hunderte von Dateien gleichzeitig offen sind.
  • HTTP-Clients oder rohe TCP-Sockets, die ewig offen gehalten werden, besonders wenn Retries neue Verbindungen erzeugen, aber alte nicht beenden.
  • Datenbank-Pools, bei denen Verbindungen auf Fehlerpfaden nicht freigegeben werden (fehlendes finally).
  • Kindprozesse, die für Konvertierung oder Scraping gestartet werden, deren stdout/stderr-Pipes offen bleiben.
  • Log- und Metrikschreiber, die pro Anfrage eine neue Datei öffnen oder Logs falsch rotieren und alte Handles offenlassen.

Warum KI-Code das verschlimmert

Generierter Code hat oft viele frühe Returns und Catch-Blöcke, aber keine konsistente Aufräumlogik. Er mischt außerdem Patterns (Callbacks, Promises, Streams) in einer Funktion, sodass leicht ein Exit-Pfad übersehen wird.

Schnelle Methoden, um zu bestätigen, dass es ein FD-Leck ist (kein Ratenraten)

Wenn du EMFILE too many open files Node siehst, beantworte eine Frage: Triffst du auf ein niedriges Limit, oder leckt deine App Dateideskriptoren über die Zeit?

Zuerst verifiziere das aktuelle Limit für den laufenden Prozess.

# In der gleichen Umgebung wie der Node-Prozess
ulimit -n

# Per-Prozess-Limits (ersetze PID)
cat /proc/PID/limits | grep -i "open files"

Als Nächstes miss, wie viele FDs der Node-Prozess jetzt offen hat, und prüfe später erneut. Ein Leck sieht aus wie eine Zahl, die weiter steigt, selbst wenn der Traffic stabil ist.

# Zähle offene Dateideskriptoren für den Prozess
ls -1 /proc/PID/fd | wc -l

Wenn möglich, sample oder graph diese Zahl. Du suchst nach einem stetigen Anstieg, der sich nicht wieder absenkt, nachdem Requests fertig sind.

Um zu sehen, was offen bleibt, mache eine schnelle lsof-Momentaufnahme und suche nach Wiederholungen.

# Übersicht, was der Prozess hält
lsof -p PID | head

# Schneller Pattern-Check (Beispiele: uploads, tmp-Dateien, sockets)
lsof -p PID | grep -E "(/tmp|uploads|\.log|TCP)" | head

Einige gängige Muster:

  • Tausende ähnlicher Temp-Dateinamen (Uploads nicht geschlossen)
  • Wiederholte Log-Dateien (Custom Logger öffnet neu)
  • Viele ausgehende Sockets (HTTP-Clients schließen nicht)

Schritt-für-Schritt: Leck isolieren und stoppen

Mach es bald bereit für Produktion
Die meisten Projekte sind innerhalb von 48–72 Stunden produktionsbereit, beginnend mit einem kostenlosen Audit.

Behandle EMFILE wie ein Ratenproblem: Etwas öffnet Deskriptoren schneller, als es sie schließt. Ziel ist es, zu beweisen, welcher Prozess und welches Feature die Zahl steigen lässt, und dann den kleinsten sicheren Fix auszuliefern.

Beginne mit Timing. Koppel den Beginn der Fehler an Traffic-Spitzen, Cron-Jobs, Queue-Worker oder Batch-Tasks. Tritt es nur während eines nächtlichen Imports auf, hast du bereits einen starken Verdacht.

Schau dann, was tatsächlich offen ist. Ein Leck durch Uploads zeigt sich meistens als viele reguläre Dateien. Ein schlechtes HTTP-Client-Muster zeigt viele Sockets in ähnlichen Zuständen. Manche Logging-Setups lassen Pipes offen.

Ein praktischer Isolate-first-Flow:

  • Identifiziere die PID, die Fehler wirft, und beobachte die offene FD-Anzahl alle 10–30 Sekunden.
  • Mache eine lsof-Momentaufnahme und scanne nach den am häufigsten wiederholten Pfaden oder Remote-Endpunkten.
  • Deaktiviere einen Worker, Job oder Feature-Flag nach dem anderen und beobachte, ob die FD-Kurve aufhört zu steigen.
  • Füge minimale Zähler um den verdächtigen Pfad hinzu (opens vs closes pro Request/Job) und logge nur Aggregaten.
  • Deploye einen gezielten Fix und bestätige, dass die Steigung unter derselben Last flach bleibt.

Für temporäre Instrumentierung halte es einfach und sicher. Für eine Upload-Route zähle, wie viele Streams du erzeugst und wie viele close oder end emittieren. Für einen Fetch-Worker logge, wie viele Responses du startest vs wie viele du vollständig konsumierst.

Wenn das Deaktivieren eines einzelnen Workers das Anwachsen innerhalb weniger Minuten stoppt, hast du wahrscheinlich das Leck gefunden. Wenn es weiter steigt, hast du möglicherweise mehrere Quellen oder eine gemeinsam genutzte Bibliothek.

Fallen, die das Leck am Leben halten

EMFILE-Probleme bleiben bestehen, wenn Cleanup nur auf dem Happy Path passiert.

Ein File-Handle, Netzwerk-Socket oder Cursor wird erstellt, dann tritt eine Exception auf, und der Close-Schritt läuft nie. Testest du nur bei erfolgreichem Ablauf, verpasst du das Leck.

Die üblichen Verdächtigen

Diese Muster tauchen oft in KI-generiertem Code auf, weil Sicherheitsbestandteile kopiert, aber weggelassen werden:

  • Kein try/finally um geöffnete Ressourcen, sodass Fehler das Schließen umgehen.
  • Streams ohne error-Handler, bei denen der Fehlerpfad Cleanup überspringt.
  • File-Watcher wie fs.watch oder chokidar, die in Produktion weiterlaufen.
  • Pro Request neu erstellte Datenbank-Clients statt Nutzung eines Pools.
  • Shutdowns, die SIGTERM ignorieren oder Aufräumen nicht abwarten, sodass alte Verbindungen während Deploys hängen bleiben.

Ein konkretes Beispiel, wie das schiefgeht

Stell dir einen Upload-Endpunkt vor, der eine Temp-Datei liest, sie an Storage sendet und dann löscht. Bei einem Timeout schlägt der Upload mitten drin fehl. Wenn der Code den Read-Stream nicht in einem finally schließt, kann der Temp-File-Handle offen bleiben. Macht man das oft genug, trifft der Server das Limit.

Ein guter Check ist, den Fehlerpfad absichtlich auszulösen (Request abbrechen, Timeout simulieren) und zu prüfen, ob die offene FD-Anzahl nach Ende der Anfrage wieder abflacht.

Wie du aus den offenen Handles Hinweise liest

Der schnellste Weg ist, zu schauen, was tatsächlich offen ist, nicht nur was du vermutest.

Sample einen Prozess ein paar Mal im Abstand von etwa einer Minute:

  • Steigt die FD-Zahl stetig bei geringem Traffic, suchst du nach einem Leck.
  • Springt sie in scharfen Stufen, schau nach geplanten Tasks (Cron), Queue-Workern oder Hintergrundjobs, die aufwachen, arbeiten und vergessen zu schließen.

Muster, die auf die Quelle deuten

Was du in lsof siehst, grenzt die Ursache oft schnell ein:

  • Viele socket-Einträge: ausgehende HTTP-Aufrufe, DB-Verbindungen, Redis-Clients, Webhooks, Proxies oder fehlende Timeouts.
  • Viele pipe-Einträge: Kindprozesse (PDF-Tools, Bildkonvertierung, ffmpeg), deren stdout/stderr nicht gelesen werden oder die nicht beendet werden.
  • Viele echte Dateien: Uploads, Temp-Dateien, Log-Dateien, Read-Streams, bei denen close nie feuert.
  • Viele ähnliche Pfade: eine Schleife, die immer dieselbe Art von Ressource öffnet.

Nachdem du den dominanten Typ identifiziert hast, gleiche ihn mit dem Timing ab. Wenn die Spitze mit einem Queue-Tick übereinstimmt, fokussiere den Worker-Code, nicht den Web-Handler. Dominieren Sockets, prüfe Connection-Pooling und Timeouts. Dominieren Dateien, prüfe Upload-Parsing und jede Nutzung von createReadStream oder createWriteStream.

Sichere Maßnahmen, während du am Fix arbeitest

Patch Lecks und Sicherheit zusammen
Schließe Sicherheitslücken beim Beheben von Stabilitätsproblemen wie exponierten Secrets und unsicheren Mustern.

Normalerweise brauchst du zwei Stränge: den Dienst am Laufen halten und Zeit kaufen, um das Leck zu finden.

Das Anheben des Open-File-Limits kann Abstürze reduzieren, behandle es aber als temporären Puffer. Wenn ein Leck weiter wächst, verschiebt ein höheres Limit nur den Ausfall. Mach eine Änderung nach der anderen, notiere Vorher/Nachher und warne, wenn die FD-Nutzung weiter steigt.

Niedrigrisiko-Maßnahmen:

  • Schnell neu starten, aber stelle sicher, dass Logs lange genug erhalten bleiben, um zu debuggen.
  • Einen Health-Check fehlschlagen lassen, wenn FD-Nutzung eine Schwelle überschreitet, damit die Instanz rotiert wird.
  • Den Endpunkt oder Job, der FD-Spitzen erzeugt, drosseln.
  • Das lecke Feature hinter einem Flag deaktivieren (Uploads, Bildverarbeitung, PDF-Generierung), bis der Fix live ist.

Timeouts sind ein nützlicher Schutz. Viele KI-generierte Apps vergessen sie, sodass langsame ausgehende HTTP-Calls, DB-Abfragen oder Consumer Sockets länger offenhalten als erwartet. Setze sinnvolle Defaults und begrenze Retries.

Sorge außerdem für vorhersehbares Shutdown: keine neuen Requests annehmen, laufende Arbeit beenden, HTTP-Keep-Alive-Agents schließen, DB-Pools schließen und Worker stoppen.

Ein realistisches Beispiel: der Upload-Worker, der Dateien offenließ

Ein Team veröffentlichte einen KI-generierten Node-Upload-Worker, der Bursts von PDFs annahm, Text extrahierte und Ergebnisse speicherte. In Tests funktionierte er, in Produktion stürzte er nach einer geschäftigen Stunde mit EMFILE ab.

Der Worker nutzte fs.createReadStream() für jedes PDF und pipte es in einen Parser. Auf dem Happy Path endete der Stream und das File-Handle schloss. Auf dem Fehlerpfad (korruptes PDF, Timeout, Parser-Exception) kehrte der Code jedoch früh zurück und räumte den Stream nie auf. Schlimmer: Es gab keine Listener für Stream-Errors, sodass manche Fehler den Catch-Block gar nicht erreichten.

Was im Patch geändert wurde

Der Fix war klein, aber strikt: Jeder Lauf musste Datei-Handles schließen, selbst wenn etwas schiefging.

  • error-Handler an alle beteiligten Streams anhängen.
  • Einen Kontrollfluss nutzen, der Cleanup garantiert (z. B. try/finally).
  • Im Aufräumen destroy() auf Streams aufrufen, die eventuell noch offen sind.

Eine vereinfachte Version sah so aus:

const rs = fs.createReadStream(path);
try {
  await parsePdf(rs); // wirft bei kaputten PDFs
} finally {
  rs.destroy(); // sicher, selbst wenn schon geendet
}

Der Nachweis in Produktion, dass es gefixt war

Sie verfolgten eine Metrik: die Anzahl offener Dateideskriptoren für den Node-Prozess.

Vor dem Patch stieg die FD-Anzahl mit jedem Burst und fiel nie wieder auf das Grundniveau. Nach dem Patch stieg sie kurz während starker Uploads und fiel dann wieder ab. Das war die echte Bestätigung, dass das Leck verschwunden war.

Kurze Checkliste, um den Fix in Produktion zu bestätigen

Hol dir ein schnelles zweites Gutachten
Teile einen lsof-Snapshot und Logs, und wir sagen dir, wo du als Nächstes suchen solltest.

Du musst nicht raten, ob du ein EMFILE-Problem gelöst hast. Du brauchst ein paar Checks, die unter echtem Traffic langweilig bleiben.

Nach dem Deployment halte dieselbe Umgebung und Arbeitslast wie beim Fehlerfall bereit (gleiche Worker, gleiche Hintergrund-Jobs, gleiche Queue-Consumer):

  • FD-Anzahl flacht ab statt zu steigen: Kleine Schwankungen sind normal; ein stetiger Anstieg ist es nicht.
  • Kein EMFILE über einen kompletten Traffic-Zyklus: Beobachte eine Peak-Periode plus ruhigere Zeit.
  • Connection-Pools beruhigen sich nach Bursts: Aktive Verbindungen und wartende Requests sollten zum Grundniveau zurückkehren.
  • Graceful Shutdown schließt tatsächlich Ressourcen: Starte eine Instanz neu und bestätige, dass der alte Prozess sauber beendet wird.
  • Ein einfacher FD-Alert: Alarmiere deutlich unter dem OS-Limit, damit Regressionen früh sichtbar werden.

Wenn die FD-Anzahl stabil ist, Fehler aber weiter auftreten, prüfe OS-Limits (ulimit), Sidecars oder andere Prozesse auf demselben Host.

Nächste Schritte, wenn es weiter auftritt

Wenn du Limits angehoben und einen Patch ausgerollt hast, aber EMFILE zurückkommt, nimm an, dass ein strukturelles Problem dahintersteckt. Zwei Muster bedeuten meistens: tiefer graben — Code, der Dateien an vielen Stellen öffnet ohne klaren Besitzer, und versteckte Hintergrund-Schleifen (Poller, Watcher, Worker), die ewig laufen und langsam Handles ansammeln.

Was du sammeln solltest, damit jemand schnell diagnostizieren kann

Bevor du mehr Code änderst, sammle ein kleines Paket an Beweisen aus der fehlerhaften Umgebung:

  • ein kurzes Log-Fenster um das erste EMFILE (mit Zeitstempeln und Traffic-Level)
  • PID, Node-Version, Container-Limits und aktuelles nofile-Setting
  • eine Open-FD-Momentaufnahme für die PID (Anzahl und dominante Typen: Dateien, Sockets, Pipes)
  • neueste Deploy-Details und was sich geändert hat
  • die Arbeitslast-Form (Uploads, Bildverarbeitung, Cron-Jobs, Webhooks, Queue-Consumer)

Danach reproduziere mit produktionsähnlicher Last für 10–15 Minuten und beobachte, ob die FD-Zahl stetig steigt. Ein stetiger Anstieg bedeutet fast immer ein Leck.

Wenn der Codebestand KI-generiert ist und du nicht schnell den „Owner" für jeden Stream/Socket findest, ist ein fokussiertes Audit oft schneller als blindes Patchen. FixMyMess (fixmymess.ai) ist genau für diese Situation gebaut: Diagnose und Reparatur kaputter, KI-generierter Node-Prototypen durch Aufspüren von Lecks, Schließen von Cleanup-Pfaden und Härtung der App für den Produktionseinsatz.

Häufige Fragen

Was bedeutet “EMFILE: zu viele offene Dateien” eigentlich in Node?

Das bedeutet, dass dein Node-Prozess sein Limit für Dateideskriptoren erreicht hat. Dateideskriptoren sind nicht nur „Dateien“; sie umfassen auch Netzwerksockets, Pipes, Verzeichnisse und Streams. Daher kann der Fehler als Datenbankfehler, kaputte HTTP-Aufrufe oder als scheinbar zufällige 500er auftreten.

Warum taucht EMFILE nach Stunden oder Tagen statt sofort auf?

Meist deutet das auf ein Leck hin: Etwas wird wiederholt geöffnet und nicht auf jedem Pfad geschlossen, besonders nicht bei Fehlern. Wenn es direkt beim Start mit wenig Traffic auftritt, ist vermutlich einfach eine sehr niedrige Open-File-Grenze für den Prozess oder Container konfiguriert.

Woran erkenne ich, ob es ein Leck oder ein zu niedriges OS-Limit ist?

Überprüfe, ob die Anzahl offener Deskriptoren über die Zeit weiter ansteigt. Wenn die Zahl konstant steigt, obwohl der Traffic stabil ist, hast du ein Leak. Wenn die Zahl stabil ist, aber trotzdem Fehler auftreten, ist das Limit vermutlich zu niedrig für deine Arbeitslast.

Was ist der schnellste Weg, um ein FD-Leck in Produktion zu bestätigen?

Beobachte die Anzahl offener FDs für die Node-PID über ein paar Minuten und dann später noch einmal. Ein Leck zeigt sich dadurch, dass die Zahl nach Beendigung von Requests oder Jobs nicht wieder auf ein Grundniveau zurückfällt, selbst wenn sie während Spitzen ansteigt.

Was sind die häufigsten Ursachen für EMFILE in KI-generierten Node-Apps?

Die häufigsten Probleme sind Streams, die bei Fehlern nicht zerstört werden, fehlende finally-Aufräumlogik nach dem Öffnen einer Verbindung oder Datei und Hintergrund-Watcher, die versehentlich in Produktion laufen. Upload-Handler, PDF-/Bildverarbeitung und Queue-Worker sind besonders anfällig, weil sie viele Handles schnell öffnen.

Wonach sollte ich in der lsof-Ausgabe suchen, um die Ursache zu finden?

Achte auf das, was offen bleibt: Viele reguläre Dateien deuten auf Uploads oder temporäre Dateien; viele Sockets deuten auf ausgehende HTTP-Aufrufe, Datenbank- oder Redis-Clients; viele Pipes deuten auf Child-Prozesse (z. B. ffmpeg). Wenn du den dominanten Typ mit dem Zeitverlauf abgleichst, kommst du meist schnell zur betroffenen Route oder dem Worker.

Warum lassen Neustarts oder Autoscaling EMFILE zufällig erscheinen?

Neustarts setzen die FD-Zahl zurück, sodass der Dienst kurzfristig „repariert“ aussieht, obwohl das Leck weiterhin besteht. Autoscaling kaschiert das gleiche Verhalten, weil neue Instanzen sauber starten, während nur einige langlebige Pods genug geleakte Handles ansammeln, um zu fallen.

Was kann ich tun, um den Dienst am Laufen zu halten, während ich am Fix arbeite?

Stoppe das Anwachsen der FD-Zahl, indem du die verdächtige Route oder den Job deaktivierst oder vorübergehend drosselst. Eine höhere Open-File-Grenze ist nur ein zeitlicher Puffer, kein Fix. Setze Timeouts vernünftig und sorge dafür, dass Shutdowns sauber aufräumen (keine neuen Requests annehmen, In-Flight-Arbeit beenden, Keep-Alive-Agenten schließen, DB-Pools schließen).

Was ist das sicherste Coding-Muster, damit EMFILE nicht zurückkommt?

Mach Cleanup unvermeidbar: Wann immer du einen Stream, Socket oder eine Pool-Verbindung öffnest, stelle sicher, dass sie in einem finally oder einem äquivalenten, garantierten Aufräumpfad geschlossen wird. Behandle Stream-Fehler explizit, denn unhandliche Stream-Fehler umgehen oft die Cleanup-Logik, von der du denkst, sie würde laufen.

Wie verifiziere ich nach dem Deployment, dass der Fix echt ist?

Beobachte ein klares Signal: Die Anzahl offener FDs für den Node-Prozess sollte während Spitzen kurz ansteigen und dann wieder in die Nähe des Ausgangsniveaus zurückkehren, statt ständig zu steigen. Wenn dein Code KI-generiert ist und du nicht schnell jeden Stream und Socket zuordnen kannst, kann FixMyMess ein kostenloses Audit durchführen und oft das Leck beseitigen sowie die App in 48–72 Stunden härten.