Wofür wir Node.js einsetzen
Zuerst für den Build. Jedes moderne Frontend braucht eine Laufzeit, die Assets bündelt, TypeScript übersetzt, CSS verarbeitet und Bilder aufbereitet. Bei uns ist das Vite, in Shopware 6 dessen eigener Build-Prozess, in TYPO3- und WordPress-Themes eine schlanke eigene Konfiguration. Dazu kommen Tests, Linting und Formatierung, die in derselben Laufzeit laufen. Wer diesen Teil nicht ordentlich aufsetzt, merkt es beim ersten Kollegen, bei dem der Build anders ausfällt.
Der zweite Einsatz sind Skripte, die nicht in die Anwendung gehören: Datenimporte, Migrationen zwischen Systemen, Aufbereitung von Medien, Aufrufe fremder APIs. Was davon in Node und was in Python entsteht, entscheidet die Aufgabe — hängt sie am Frontend-Ökosystem, bleibt sie in Node; geht es um Datenanalyse und Aufbereitung, ist Python die bessere Wahl. Drittens, seltener, echte Dienste: kleine APIs, Websocket-Verbindungen, Verarbeitung von Ereignissen.
Wie wir damit arbeiten
Die Node-Version wird im Projekt festgeschrieben, nicht dem Zufall auf dem Rechner überlassen. Abhängigkeiten stehen mit Lockfile im Repository, Builds laufen im Container, damit lokal und in der Continuous Integration dasselbe herauskommt. Bei Paketen sind wir zurückhaltend: Jede Abhängigkeit ist Code, den jemand aktualisieren muss, und eine Angriffsfläche über die Lieferkette. Ein npm-Baum, der für eine Handvoll Funktionen halbe Ökosysteme nachzieht, ist kein Fortschritt.
Läuft doch ein Dienst dauerhaft, behandeln wir ihn wie jede andere Anwendung im Betrieb: Prozessverwaltung, Neustartverhalten, Protokolle, Überwachung, Update-Pfad für Node selbst. Gehostet wird auf unseren eigenen Servern in Deutschland, im Proxmox-Cluster, mit Support Mo–Fr von 9:00 bis 16:00 Uhr. Die Betriebsfrage klären wir vor der ersten Zeile Code, nicht bei der Übergabe — sie entscheidet oft, ob der Dienst überhaupt gebaut wird.
Grenzen: wann kein Node-Dienst entsteht
Ein Node-Dienst ist schnell geschrieben und lange zu betreuen. Deshalb fragen wir zuerst, ob die Aufgabe nicht in die bestehende Symfony-Anwendung gehört — als Kommando, als Message-Handler, als Endpunkt. Dort gibt es bereits Deployment, Rechteverwaltung, Datenbankzugriff und jemanden, der sich auskennt. Ein zusätzlicher Dienst bedeutet einen zweiten Update-Zyklus, ein zweites Protokoll und im Zweifel den einen Prozess, an den nach zwei Jahren niemand mehr denkt.
Rechenintensive Arbeit gehört ebenfalls nicht in Node. Die Ereignisschleife ist stark bei vielen gleichzeitigen Verbindungen und schwach, sobald ein Vorgang die CPU längere Zeit belegt — dann steht alles andere. Bildverarbeitung, große Auswertungen, umfangreiche Datentransformation laufen bei uns in Python oder in einer Warteschlange außerhalb. Und für klassische Webanwendungen bleibt PHP 8 mit Symfony gesetzt. Node ist dort keine Verbesserung, sondern nur eine andere Sprache.