In the history of computing, 1995 was a crazy time. First Java appeared, then close on its heels came JavaScript. The names made them seem like conjoined twins newly detached, but they couldn’t be more different. One of them is compiled and statically typed; the other interpreted and dynamically typed. That’s only the beginning of the technical differences between these two wildly distinct languages that have since shifted onto a collision course of sorts, thanks to Node.js.

If you’re old enough to have been around back then, you might remember Java’s early, epic peak. It left the labs, and its hype meter pinned. Everyone saw it as a revolution that would stop at nothing less than a total takeover of computing. That prediction ended up being only partially correct. Today, Java dominates Android phones, enterprise computing, and some embedded worlds like Blu-ray disks.

For all its success, though, Java never established much traction on the desktop or in the browser. People touted the power of applets and Java-based tools, but gunk always glitched up these combinations. Servers became Java’s sweet spot.

Meanwhile, what programmers initially mistook as the dumb twin has come into its own. Sure, JavaScript tagged along for a few years as HTML and the web pulled a Borg on the world. But that changed with AJAX. Suddenly, the dumb twin had power.

Then Node.js was spawned, turning developers’ heads with its speed. Not only was JavaScript faster on the server than anyone had expected, but it was often faster than Java and other options. Its steady diet of small, quick, endless requests for data have since made Node.js more common, as webpages have grown more dynamic.

While it may have been unthinkable 20 years ago, the quasi-twins are now locked in a battle for control of the programming world. On one side are the deep foundations of solid engineering and architecture. On the other side are simplicity and ubiquity. Will the old-school compiler-driven world of Java hold its ground, or will the speed and flexibility of Node.js help JavaScript continue to gobble up everything in its path?

Where Java wins: Rock-solid foundation

I can hear the developers laughing. Some may even be dying of heart failure. Yes, Java has glitches and bugs, but relatively speaking, it’s the Rock of Gibraltar. The same faith in Node.js is many years off. In fact, it may be decades before the JavaScript crew writes nearly as many regression tests as Sun/Oracle developed to test the Java Virtual Machine. When you boot up a JVM, you get 20 years of experience from a solid curator determined to dominate the enterprise server.

The JavaScript world is catching up quickly. When much of the entire web depends upon the JavaScript execution engine, a bazillion developer hours go into polishing all of the edges. But all of the innovation has a downside because the new features may be proliferating faster than the developer base can absorb them. Old school developers are often confused by code filled with the newer ECMAScript syntax enhancements—and this same new code will quietly crash some older browsers. The endless supply of innovative preprocessors like CoffeeScript and JSX may be great for developers who want those features, but they make it harder for the rest of us to open up a random file and understand it immediately.

Java has its share of new features and options, but for the most part it is a stable platform. That makes life much easier for developers who are building something to last.

Where Node.js wins: Ubiquity

Thanks to Node.js, JavaScript finds a home on the server and in the browser. Code you write for one will more than likely run the same way on both. Nothing is guaranteed in life, but this is as close as it gets in the computer business. It’s much easier to stick with JavaScript for both sides of the client/server divide than it is to write something once in Java and again in JavaScript, which you would likely need to do if you decided to move business logic you wrote in Java for the server to the browser. Or maybe the boss will insist that the logic you built for the browser be moved to the server. In either direction, Node.js and JavaScript make it much easier to migrate code.

Node’s lead in this world only seems to be expanding. The most sophisticated web frameworks, like React, will decide at the last second whether to run the code on the server or the client. One day it will run on the client and on another day it will run on the server. Some smart logic will make the decision on the fly based upon load or spare RAM or something else. Some frameworks will ship JavaScript to the database as a query where it is executed. Your code could be running anywhere and it’s getting harder to keep up because it doesn’t send a postcard home. Just be happy because you don’t need to think about the details.

Where Java wins: Better IDEs

Java developers have Eclipse, NetBeans, or IntelliJ, three top-notch tools that are well-integrated with debuggers, decompilers, and servers. Each has years of development, dedicated users, and solid ecosystems filled with plug-ins.

Meanwhile, most Node.js developers type words into the command line and code into their favorite text editor. Yes, some of the best text editors like Atom have elaborate collections of plug-ins that do almost anything, but even then it feels like Node.js is more old school than Eclipse. Soon we’ll be replacing our mouse with an Atari joy stick.

Some developers use Eclipse or Visual Studio, both of which support Node.js. Of course, the surge of interest in Node.js means new tools are arriving, some of which, like IBM’s Node-RED offer intriguing approaches, but they’re still a long way from being as complete or as dominant as Eclipse or IntelliJ.

The weird thing is that the developers don’t seem to use these tools. The command line was supposed to disappear 35 years ago with the arrival of the Mac, but no one told the Node.js developers. The options are there. WebStorm, for instance, is a solid commercial tool from JetBrains that incorporates many command-line build tools.

Of course, if you’re looking for an IDE that edits and juggles code, the new tools that support Node.js are good enough. But if you ask your IDE to let you edit while you operate on the running source code like a heart surgeon slices open a chest, well, Java tools are much more powerful. It’s all there, and it’s all local.

Where Node.js wins: Database queries

Queries for some of the newer databases, like CouchDB and MongoDB, are written in JavaScript. Mixing Node.js and a call to the database requires no gear-shifting, let alone any need to remember syntax differences.

Meanwhile, many Java developers use SQL. Even when they use the Java DB—formerly Derby, a database written in Java for Java developers—they write their queries in SQL. You would think they would simply call Java methods, but you’d be wrong. You have to write your database code in SQL, then let Derby parse the SQL. SQL is a nice language, but it’s completely different from Java, and many development teams need different people to write SQL and Java.

To make matters worse, many Java coders use elaborate libraries and schemes to convert the data from the SQL query into Java objects just so they can recast it into templates. It’s a crazy process, and ultimately pretty wasteful.

Where Java wins: Types

Many of the introductory programming courses continue to use Java because many serious programmers tend to like statically typed code both for the simplicity and the safety. The code just feels more rigorous after the compiler catches the obvious bugs.

JavaScript, though, is catching up and some developers are switching over to TypeScript, a statically typed superset of JavaScript that applies all of the type-checking magic before spitting out something that runs in your browser’s JavaScript stack. If you love types, this may be enough for you to embrace JavaScript. Or you could just recognize the imitation as the sincerest form of flattery and stick with Java, which embraced static typing from the beginning.

Where Node.js wins: Syntactic flexibility

JavaScript used to be a simple language for popping up unwanted alert boxes and double-checking form input. Then the developer community created many different versions of the language that could be transpiled into something for the browser. There is the CoffeeScript crowd offering a handful of different syntaxes designed to satisfy a taste for cleaner punctuation. There is the React/Vue crowd that mix together HTML and JavaScript just because it’s cleaner. There is TypeScript for the type lovers and LiveScript for the functional language devotees.

You’ll find a tremendous amount of creativity in the Java world too, but for some reason it isn’t expressed with many pre-processors. There are a number of languages like Kotlin, Scala, and Clojure that are turned into byte code for the JVM, but somehow they feel different enough to stand apart as separate languages. All of the preprocessors make life more fun for JavaScript programmers who love different ways to formulate or punctuate their code.

Where Java wins: Simple build process

Complicated build tools like Ant and Maven have revolutionized Java programming. But there’s only one issue. You write the specification in XML, a data format that wasn’t designed to support programming logic. Sure, it’s relatively easy to express branching with nested tags, but there is something annoying about switching gears from Java to XML merely to build something. With JavaScript, there’s no switching gears.

Node.js used to have the simpler build. You would just edit the code and then hit “run.” That was then. As the Node developers have “improved” the process, they’ve added preprocessors that take your favorite subdialect of JavaScript and turn it into something runnable. Then the Node package manager needs to find the right library. Most of the time this just works, but sometimes it doesn’t and then you’re spending time looking for the right version number of some artifact that you’re building yourself in a separate step. And if you commit some mistake to the artifact repository, well, that version number is shot and you’ve got to turn the odometer wheels again.

Java also has a complex build process that is pretty similar to the Node.js method, but it doesn’t feel like it has gotten any more complex. Somehow Maven and Ant seem like part of the Java foundation now. Many of the rough edges are long gone and the builds just work more often. If there were some absolute measure of build hassle, the two languages might be similar, but the rapid explosion of JavaScript complexity means that Java wins.

Related video: Node.js tips and tricks In this explainer video, learn several techniques that can improve your Node development experience.

Where Node.js wins: JSON

When databases spit out answers, Java goes to elaborate lengths to turn the results into Java objects. Developers will argue for hours about POJO mappings, Hibernate, and other tools. Configuring them can take hours or even days. Eventually, the Java code gets Java objects after all of the conversion. And when it comes to configuration, the Java world still clings to XML and even offers two major parsers to give developers more reasons to fret.

Today, many web services and databases return data in JSON, a natural part of JavaScript. JSON is now so common and useful that many Java developers use the format, and a number of good JSON parsers are available as Java libraries as well. But JSON is part of the foundation of JavaScript. You don’t need libraries. It’s all there and ready to go.

Where Java wins: Remote debugging

Java boasts incredible tools for monitoring clusters of machines. There are deep hooks into the JVM and elaborate profiling tools to help identify bottlenecks and failures. The Java enterprise stack runs some of the most sophisticated servers on the planet, and the companies that use those servers have demanded the very best in telemetry. All of these monitoring and debugging tools are quite mature and ready for you to deploy.

Where Node.js wins: Desktop

There may be some Java applets running out there, and I still maintain some Java JAR files that I can click on to run, but for the most part the desktop world is largely Java free. JavaScript, on the other hand, continues to capture more and more of the action as the browser eats up most of the roles for our desktop. When Microsoft rewrote Office to work in the browser, the die was cast. If you’re still wondering, there are interesting options like Electron that take your web code and turn it into a stand-alone desktop app.

Where Java wins: Handhelds

Android apps are often written in Java and 90 percent of the new phones run some version of Android. Many people don’t even use desktops any more because the phones are good enough for everything.

Of course there is a bit of confusion. Many developers are writing Node.js web apps that target the mobile browsers on both the iPhone and the Androids. If this is done well, the performance is often good enough.