There is more than just Node

Published Mar 10, 2018Last updated Mar 21, 2018

I've spent some time reading articles here on codementor and I've seen a lot of love go around for Node.js as a platform. This praise is warranted, Node is a fantastic technology for getting a performant API running that connects multiple services - databases, other APIs, etc. I did this for several years in a few different projects, and even contributed some packages to NPM that are still in use today. The advantages of working purely in JS, the simplicity of interacting with JSON, and the massive number of libraries all make Node a pleasure to work in.

But there's one thing I've seen repeat itself over and over in the technology industry, and that is the nerdlove. Developers fall in love with technologies and forget that both other things exist, and that their favourite technology makes technical tradeoffs and sometimes those tradeoffs are not useful for the task at hand. I've run into some of these tradeoffs while developing Node applications, and I'd like to share some my experiences with that and remind everybody that there are other things out there.

The first alternative technology I will talk about today is TypeScript, which is a compile-to-Javascript language released by Microsoft a few years ago. I know that many Node developers these days shun compile-to-JS languages and for good reason: many of the previous ones while gaining popularity for a while have fallen by the wayside because they didn't really offer a whole lot on top of JS other than a slightly different syntax. CoffeeScript is a great example, it was mostly just a cleaner Ruby/Python-ish syntax for Javascript semantics and so didn't quite have the staying power of a different language with actual benefits.

TypeScript is a bit different. It is a superset of Javascript, meaning that you can just write Javascript, run it through the TypeScript compiler, and it will just work. Because of this, you can begin adopting TypeScript gradually, and use the features of TypeScript that are useful to you. The advantage that TypeScript adds to Javascript is that you can annotate types in your code and have a compiler check those types just like it would in a statically-typed language. However since it is optional, it does not get in your way nearly as much as they do in a statically-typed language.

When might you want to use TypeScript? Where it really shines is when you have an existing Node-with-Javascript system that has many components talking to each other over a network via message queues, APIs, etc. If a developer modifies the system but forgets to fix it on the other side, you can end up with a type inconsistency. Unit tests don't save you here because they are designed to test a single component in isolation (hence the name "unit"), and good integration test suites by nature are difficult to write due to the combinatorial explosion of input possibilities and in practice often don't exist at all. Having a compile-time check at the interfaces between your components helps to ensure that everyone is speaking the same language. Protocol buffers are really useful here since they are language-agnostic, but just using a shared class can be useful too.
I've also found that explicitly declaring your types helps to onboard new folks much faster, especially juniors. When someone is new they don't really understand what fields are available or what they do; your type declarations are useful documentation that does not go out of date.

What are the downsides of TypeScript over Javascript? The main one is that you need a build step when deploying your code. This gets a bit in the way of the write-run cycle that you often use in Node that allows people to develop very quickly. Since the main benefits of TypeScript don't kick in until you have more people on your team or when you have a more mature product, it is less suited to a quick rapid-iteration style that you would use in an early stage startup.

Who is using TypeScript? Some notable examples eBay, Angular (and other parts of Google as a whole), Ericsson, and Kaggle. You can see many others on TypeScript's

Let's move a little bit farther away from Javascript now. TypeScript is great, but you're still running on top of Node, still using NPM, etc. and so it still has the same problems that Node has. The next language I want to talk about is Go, a systems programming language out of Google that was originally designed to replace C++, but ended up getting used for all sorts of other things.

Unlike TypeScript, Go requires all types to be explicitly defined, compiles to a binary instead of being interpreted, and unlike the underlying Node.js system that TypeScript uses, is multi-threaded. Because Go's goroutine system is so lightweight, it doesn't need asynchronous function calls to be fast. This is a huge win, since you no longer find yourself falling into callback hell, or having to mess around with complicated Promise chains.

Many people in the Node community are skeptical of statically-typed languages like Go because they are accustomed to older languages like C++ and Java, which are rather verbose and require a lot of boilerplate to just be to satisfy the compiler. Go's type system is much simpler and while many in the statically-typed world have their criticisms of it, I've found that people coming from dynamically-typed languages like Javascript, Python, and Ruby prefer the type system in Go because it more closely matches the way that people write code in these languages.

When might you use Go? One of the major disadvantages of Node is that it is single-threaded, so if you have something that is CPU-heavy like string processing, number crunching, schema enforcement, etc. then your Node server will lock up while it's busy chugging away at that calculation. Since Go is multi-threaded, it can have some goroutines handling new connections while different ones manage the processing (which itself is much faster because of the native-compile).

Another advantage that Go has is its footprint. If you're running a large-scale setup on cloud VMs and you find yourself paying tons of money for them, Go might be a useful replacement for your widely deployed services since it makes much more efficient use of CPU and RAM than Node. An example from my experience was when I was running some chat servers on a Digital Ocean micro instance (512 MB RAM) I could only run 2 Node processes per instance before they started to run out of memory. Each Node process would use up about 200MB of RAM and about 30% of the CPU. Re-writing these servers in Go which only took a day or so, they would use about 10MB of RAM and less than 1% of the CPU.

Lastly, since Go is statically-typed then some of the same reasons that TypeScript is useful also apply to Go.

What are the disadvantages? Like TypeScript, Go has a build step involved, although you can run a program directly by using the go run command-line tool. Build times are fast enough that it's not too different from running an interpreted program, but it is still an extra hurdle and can often result in some weird compiler errors when you are still new to the language.

In Go it's a bit annoying to use data structures other than arrays and maps since they have to be "dynamically" typed, you often have to fiddle around with casts to make the compiler happy.

A downside compared to TypeScript is that you can't just start using it within an existing Node application, you have to rewrite things. I have done this in the past, although since I was using RabbitMQ for my components to talk to one another, it was a pretty simple process of re-writing one module that was CPU-bound and taking too long. If your application is more monolithic, then you might have too many headaches untangling things to make a switch to Go worth it.

Who is using it? For one, I do at Apigee, and did at YouTube for some applications. Other users are Docker, Kubernetes, Istio, not to mention a rather large list posted on Go's Github repo.

This is just a quick survey of two alternatives to Node. There are plenty of other new languages that pop up all over the place, but I chose these ones because at this point in time they are fairly mature and have proven useful in production environments, and they are often used in similar applications as Node such as REST APIs and server-side infrastructure. If you're like me and ran into growing pains as your application scaled up, then hopefully these choices help you out!

Discover and read more posts from Rob Britton
get started