Node.js
Node.js runs JavaScript outside the browser on V8. Its design choice is a single-threaded event loop with non-blocking I/O: rather than a thread per connection, one thread handles many connections by never waiting on I/O.
That model is excellent for I/O-bound work — many concurrent connections doing little computation each — and poor for CPU-bound work, because a single long computation blocks everything. The rule follows directly: Node is a good fit for an API gateway or a realtime server, and a bad fit for data processing, which is Python’s work in my stacks.
Its actual role here
In this garden Node is mostly build tooling rather than an application runtime. Vite runs on it, the client generator runs on it, and the Nuxt server runtime is the one place it serves requests in anger. Backends are FastAPI or Django.
That is worth stating plainly because “we use Node” usually implies a JavaScript backend, and here it does not. The dependency is on the tooling ecosystem, which is unavoidable for modern frontend work regardless of what the backend is written in.
The dependency problem
node_modules is the well-known joke and the underlying issue is real. npm’s flat-ish resolution allows multiple versions of the same package, so a modest application has a transitive tree of hundreds to thousands of packages, most of which nobody has evaluated.
Two practical consequences. Supply chain surface is large — you are trusting every maintainer in that tree, and the ecosystem has a history of incidents. Reproducibility requires discipline: the lockfile must be committed and npm ci used rather than npm install in CI, or dependency versions drift between environments.
Neither is solved by tooling choice. pnpm improves disk usage and strictness, and the tree is still the tree.
The deeper issue is that Node ships almost no standard library by comparison with Python, so functionality that would be built in elsewhere arrives as a dependency. That is a cultural difference with permanent consequences, not a fixable defect.
Version management
Node moves quickly and projects pin to versions. Something has to manage that — nvm, or in my case pinning the version in the same declarative configuration as everything else through devenv, which puts the runtime in the same commit as the code that needs it.
See also: Vite, Nuxt 3, Vue 3, and Python for the comparison.