Let me start by saying, Node.JS could be an option for enterprises but *not* for enterprise applications. What I mean here, for small or medium size applications having web-facing infrastructures such as mobile apps, apps requiring real-time, two-way connections (e.g. chat, real-time stock quote), and those using microservice architecture (i.e. single responsibility), Node has provided an alternative to many server-side frameworks. As we know, with the advent of IoT & Digital transformation, business is changing rapidly and many startups are popping up. So, for responding quickly to some urgent business requirements, without any doubt the Node.js model is worth your attention because of its low resource footprint and ability to spin up something quickly. But, I have my doubts about developing large scale enterprise applications using Node.js.
Let’s first try to understand what we call an enterprise application. As per Gartner: Enterprise application software includes content, communication, and collaboration software; CRM software; digital and content creation software, ERP software; office suites; project and portfolio management; and SCM software. Typical enterprise applications like CRM, ERP, Accounting & Banking apps are multi-user, multi-machine, multi-component, multi-screen, and multi-developer. They manipulate massive data and utilize extensive parallel processing, with complicated data relations, complex business rules, distributed computing & transactions, and require heavy integration with other applications. While enterprises are moving towards microservice architecture, there are certain applications (legacy systems, batch applications, SCM) that are inherently monolithic and can’t be replaced. Enterprise software is intended to solve an enterprise-wide problem rather than a departmental problem.
Node.js is not a silver bullet for developing software and definitely not suitable for everything especially large-scale, mission-critical enterprise applications mainly because of its single threaded architecture, event-driven async programming model, limited transaction management support, and a few other constraints. Let’s discuss some of these limitations in detail to understand why Node.js is unfit for such large enterprise applications.
Also, everything is asynchronous—which hurts. Coding consists of callbacks within callbacks within callbacks… it’s a Callback hell—pretty messy code, very difficult to understand and maintain. There are ways for having better code and managing callback hell, but then we are relying too much on having good practices and disciplined programmers.
Node developers generally initialize webserver and run business code in the same process—there is no isolation between the application server and business process which other mature servers like Tomcat or Apache HTTP servers provide. Also, not having any isolation leads the server to crash if business code throws some exception.
The way npm is structured also makes it quite difficult to find trustable packages. As it is open to all, anyone can publish their own modules making it harder to spot reliable, stable, and mature packages. Not being backed by a standard body, using NPM packages is still a risky game. Here is an interesting article on how one developer broke Node.
There are a few other limitations which will prevent Node.js from being a choice enterprise application technology stack. There's no support for distributed transactions, limited debugging & IDE support (StrongLoop debugger works only in a couple of browsers), a lack of standard and matured libraries, and a lack of a good IDE which seriously impacts development. According to my experience, explicitly typed languages are more readable, generate robust code, and have good IDE + testing tool support.
While Node is working on a security project—and security is a top priority—it isn't rock solid against attacks. And, the availability of the Node application is questionable which makes Node application for a few sectors like financial services, banking, and investment worrisome.
While Node.js has an attractive ecosystem, I am surprised when people are comparing Node.js with a solid Java technology stack. I am not a Node.js expert and have never worked with it in a real serious basis; but yes, I am quite familiar with the Java stack and hence decided to compare a few important features of Node.js with equivalent features/frameworks available within the Java Ecosystem.
Single Threaded Node.js Event Loop vs. Servlet 3.0 Async Feature
With servlets 3.0 Async feature, resource-intensive execution can be decoupled from the Servlet container thread and delegated to a worker thread. By releasing the initial request processing thread back to a container, it will significantly increase the throughput and scalability of webserver. The released container thread can be used to accept and process new incoming request connections. This way the container thread pool is never exhausted even if there are too many concurrent requests.
This approach of having multiple container threads accepting requests concurrently and using worker threads to execute resource-intensive tasks asynchronously is far more superior to Node.JS event loop. This design is capable of utilizing multiple CPU cores which are available in latest hardware which obviously gives far better performance than a single threaded model.
JDK 7 onwards, Java also supports buffer oriented, Non-blocking I/O using channels. Basically, with the help of NIO, data is read from channels into buffers and written from buffers into channels. Even in Servlet 3.1, which now supports NIO using Read & Write listeners, has callback methods. These methods are invoked only when the content is available to be read or written without blocking.
This has helped web servers like Tomcat & Jetty tremendously. Now in HTTP 1.1, connections can remain alive (i.e. connections are persistent) between client and webserver between subsequent requests. This means a single TCP connection can be used to send multiple HTTP requests/responses and now large numbers of concurrent users can be served with limited container threads.
As we know, Node.js achieves much of its speed because of it is single threaded (no context switching), asynchronous event-driven, and supports non-blocking I/O. But likewise, the Java ecosystem has a few options like Spring Reactor, Vert.x, and Akka which are promising event-driven and non-blocking server frameworks that can utilize multiple CPU cores for achieving high scalability without the complexity of handling threads. Performance-wise also, if you ignore the warm-up time, the absolute performance of Java applications is much better. By the way here is one of the latest performance test comparisons of several web application platforms which clearly shows many Java-based frameworks like Servlet, Jersey, Tapestry, Dropwizard, etc. are really fast.
Server Push & Bi-directional Communication
In the absence of Websocket, I remember using Flex, Long polling, Comet, etc. for two-way communication—especially for pushing data to browsers. Websocket in now formally introduced in HTML5 and even other technologies/frameworks have adopted it as well. For example, based on JSR 356, Servlet 3.1 now provides Websocket support. Spring MVC and Tomcat7 also support web sockets. So, in a nutshell, both node.js and the Java stack have very similar Websocket implementations.
As we can see, the JVM world is evolving rapidly, becoming asynchronous, reactive, and functional. Also, frameworks are becoming more mature, providing built-in support to both develop and deploy applications rapidly (e.g. SpringBoot). Thus, in comparison with Node.js, the JVM ecosystem is unmatched—there are lots of use-cases with readymade solutions and a vast array of libraries (including many apache projects). Not to mention, Java has a rock-solid foundation, proven track record, threading capabilities, matured IDEs, debugging capabilities, and lots more. Considering all this, I would say the Java stack is far more matured and proven to be enterprise friendly.
As per Gartner’s “Bimodal IT” model, organizations now require two separate and coherent groups: one which takes care of the traditional IT operations, running today’s enterprise apps and executing typical enterprise operations (e.g. CRM, ERP, mainframe applications). The other one explores and develops next-generation applications which require fast turnaround and rapid changes to transform business ideas into applications. So for the latter, Node could be an option considering its benefits... but, for the other type of application, to really deliver value, they need to interact with transactional systems (i.e. with type-1 applications). Depending on your requirements, choose your technology stack judiciously rather than following the crowd impulsively.
As concluding remarks, I must say that Node.js can complement existing enterprise technology stacks instead of replacing them.