What we use Node.js for
The build comes first. Every modern front end needs a runtime that bundles assets, compiles TypeScript, processes CSS and prepares images. For us that is Vite, in Shopware 6 its own build process, and in TYPO3 and WordPress themes a lean configuration of our own. Tests, linting and formatting run in the same runtime. Set this part up carelessly and you find out with the first colleague whose build turns out differently.
The second use is scripts that do not belong in the application: data imports, migrations between systems, preparing media, calling third-party APIs. Whether something is written in Node or in Python depends on the task — if it hangs off the front-end ecosystem it stays in Node; if it is about analysing and preparing data, Python is the better choice. Third, and less often, actual services: small APIs, websocket connections, event processing.
How we work with it
The Node version is fixed in the project, not left to whatever happens to sit on the machine. Dependencies live in the repository with a lockfile, builds run in a container so that local machines and continuous integration produce the same result. We are restrained about packages: every dependency is code someone has to keep updated, and an attack surface through the supply chain. An npm tree that drags in half an ecosystem for a handful of functions is not progress.
If a service does run permanently, we treat it like any other application in operation: process management, restart behaviour, logs, monitoring, and an update path for Node itself. Hosting is on our own servers in Germany, in the Proxmox cluster, with support Monday to Friday, 9:00 to 16:00 CET. We settle the question of who runs it before the first line of code, not at handover — it often decides whether the service gets built at all.
Limits: when no Node service gets built
A Node service is quick to write and long to look after. So we first ask whether the task belongs in the existing Symfony application — as a command, as a message handler, as an endpoint. Deployment, permissions, database access and someone who knows their way around are already there. An extra service means a second update cycle, a second log, and, in case of doubt, the one process nobody remembers two years later.
Compute-heavy work does not belong in Node either. The event loop is strong with many simultaneous connections and weak as soon as a single operation occupies the CPU for any length of time — then everything else waits. Image processing, large analyses and bulk data transformation run in Python here, or in a queue outside. And for classic web applications PHP 8 with Symfony stays the choice. Node is no improvement there, only a different language.