Node.js for Enterprise Applications! Are You Kidding?
Amidst all the hype about using Node.js, still a question remains... Can Node.js be used to develop Enterprise grade applications? Author Mihir Shelat argues Java would be a better option.
Join the DZone community and get the full member experience.
Join For FreeNowadays, the JavaScript runtime called Node.js (which of course is quite promising) is becoming a popular choice for developing server-side web applications. Amidst all the hype about using Node.js, still a question remains... Can Node.js be used to develop Enterprise grade applications?
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.
Since Node.js has a single-thread JavaScript event loop, when it executes long-running or high computational intensive tasks (which is quite common in enterprise applications), it queues all the incoming requests to wait for execution. This will result in poor performance. Also, it doesn’t scale out to take advantage of the multiple cores commonly present in today’s server-class hardware. So, the execution of Node.js on server-class hardware results in heavy utilization of one CPU core while leaving the other CPU cores underutilized... hence, the solution is not scalable enough. Alternatively, to scale out you need to offload such CPU intensive tasks to other Node.js servers (node cluster) which is not always advisable as it requires additional hardware and maintenance difficulties. So, for typical enterprise applications (e.g. batch processing) where you need multi-threaded execution with controlled and cohesive inter-thread communication, Node is not suitable.
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 weak type nature of JavaScript and Node.js makes it easy to leak defects, no compilation phase, and no type checking meaning that code is lot more prone to bad references or null pointer exceptions which are discovered at runtime. Especially with large enterprise applications having larger code and multiple developers working on the same code base, the missing types are more a problem for productivity than an advantage. Actually, in weak typed languages, the programming discipline must be even stricter than in strongly typed ones.
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.
Frameworks like Spring MVC 3.2+, Jersey 2.x (JAX-RS 2.0) are based on Servlet 3.0 specification and have adopted its asynchronous model.
Non-Blocking I/O
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.
Event-driven
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.
Related Refcard:
Published at DZone with permission of Mihir Shelat. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments