Why we migrated our CLI from NodeJS to GoLang 💻

Eugene Cheah on March 15, 2019

"Why we" articles are meant share about our engineering considerations and decisions, but it does not mean our decision would be the best for your... [Read Full]
markdown guide

You could use ncc from Zeit to compile NodeJS to a single file


Hmm, ur right should have gave it a try did honestly miss this one 😅


There's even Zeit's pkg which I believe builds on the work of ncc. It generates a binary so you don't even need node installed.

GitHub logo zeit / pkg

Package your Node.js project into an executable

Build Status Coverage Status Dependency Status devDependency Status Join the community on Spectrum

This command line interface enables you to package your Node.js project into an executable that can be run even on devices without Node.js installed.

Use Cases

  • Make a commercial version of your application without sources
  • Make a demo/evaluation/trial version of your app without sources
  • Instantly make executables for other platforms (cross-compilation)
  • Make some kind of self-extracting archive or installer
  • No need to install Node.js and npm to run the packaged application
  • No need to download hundreds of files via npm install to deploy your application. Deploy it as a single file
  • Put your assets inside the executable to make it even more portable
  • Test your app against new Node.js version without installing it


npm install -g pkg

After installing it, run pkg --help without arguments to see list of options.

The entrypoint of your project is a mandatory CLI argument. It may be:

  • Path to entry file. Suppose it…

Thanks! I'll remember this tip when I embrace Node in future and feel swayed by Golang propaganda. :P


Did you consider Rust? IMHO it has a more flat learning curve compared to golang and it meets all the requirements.


Rust seems interesting from an engineering and programming language design point of view, but the syntax is so ugly. I tried, but I can't program in it for longer than a snippet.


hahaha, interesting I feel just the other way around I have tried Go a few times and the syntax seems to be ugly and very heterogeneous for me.

Rust clicked with me as well, much easier than go. Before that I would say python clicked better with me than Ruby. Just to give some context.

I'm happy to have all of them s an option overall.

I share greatly your ending sentiment. While I dislike python and ruby also I’m glad they have enabled so many others.


I love Rust, and write about it here frequently.
But I would never insinuate its learning curve is anywhere near as forgiving as go's. =)


I am not a Rust programmer, I have just used Rust and Go for side projects, and maybe because of my background or for the available resources, Rust was easier for me than Go.

That has been said, I was sharing my experience based on my context and I wanted to know if they already have tried Rust and why did they discard it.


Came here to say this.
Structured parsing of JSON in Rust is wonderful.

Foiled by golang once again.


Gosh, thats a good idea : worth giving it a spin next time 👍


It would be interesting to see a comparison :D


needs to be saved. btw you did not consider awesome python ...


python is (unless you're doing ML, which you shouldn't be) not awesome


I personally really dislike the syntax, and the code is inconsistent to what I think it should do. Also, going off your points, does not create a single distributable, has tons of dependencies, version conflicts, and the syntax is compiler enforced.

version conflicts and dependencies is solved by py companies, not an issue if you use your own version. single exec, pyinstaller has been killing lately but even without single exec, py companies have no problem.

for syntax dislike and enforcement, that is a matter of choice.

industrial-level python is different from casual coding.


We actually did, python, ruby, and a few others... they been removed in the article due to the repetition of the reason - which is the end user needing to install an external language library as a dependency before using the CLI (which is mentioned in java and js). Someone in the team even joked about considering PHP (its possible btw)

On another topic : we even considered c and c++, but that might be a bit too difficult for the team to do well without bugs (or overflow vulnerabilities)

One of our benchmarks for example is the ability to run in vanilla alpine.


na na you need to study py engineering particularly distribution. XD for distribution you just install your program. companies using py for production, include libs needed etc so that you install it like any other software.

e.g. if flask is needed, they choose a version for in-office use and that lib is shipped across products, they don't pip install or anything online in target env or even in dev


The ooooooone point I might argue is zero-dep. I build go for scratch base images all the time. Scratch is literally zero bytes, and only provides /.

As for learning curve... Yes. It's a bit of a beast lol. gofmt helps a lot - intellij, with its auto gofmt helps more.

Dealing with json - especially uncertain json - is... I don't talk about that.

For me, the draw was true cross-compile, and it's sheer perf. If you need quicker than Go, you need C.

I don't need C 😂


😂 and I have met folks who thinks my alpine approach is "hardcore" haha.

And yes I so want go to have a better way to handle uncertain json data.


What about Java with graalvm native image? Or even node with graalvm native image..


Never heard of it, but just took a look into.... and holy batman!

While not so comfortable with the way it does things internally. I am impressed, in the crazy sense that they are pushing the idea of compiling programs, not just to exe's but to run within Oracle / My SQL.

Shameless self plug here : its like GPU.JS style of crazy rewrites (of JS to WebGL).... Dun ask why we compile from one language to another which makes no sense... just know it has been done.


The interesting part is that the node execution performance is almost 85% for V8 and GraalVM is still in beta. Hopefully they will manage to reach the same performance and then you could compile you node app into a native one and have no drawbacks. Currently a JAX-RS rest endpoint compiled into native boots in ~5ms and uses 20mb of ram.

I like that GraalR runs an order of magnitude faster than the reference R runtime :D


public knowledge of what or how to use graal is very low unfortunately..


BTW of course you can create single binaries with node. Just use pkg or nexe!


Didn't try pkg (should have honestly), nexe did sadly create a large package for us - which is a known issue on their part : they are working on it 😄


Yeah ... Anyways, Golang is very awesome, although I recently switched back to Node simply for it's simplicity.


Java has made major improvements in both language constructs and deployment models in the last few years (9 and 11 in particular). Although go is fun for small projects, and wins the too cool for school award, single file lightweight deployment of java is now an off-the-shelf supported option. See steveperkins.com/using-java-9-modu... for more information.

Note that all single file deployment solutions are still os dependent, go, java, etc. So you still have to maintain multiple build chains.

Interestingly, with the embedded jvm approach, you also enable development in multiple languages, such as kotlin , scala and groovy and still have a single file deployment.

There may be other reasons to reject java, just not so sure it is such an easy call.


The icons at the end could be a winning argument for just about anything.


Nice reference to physics! My post-read nerd stokedness level: maximally high.


Thanks for a nice article, but I will need to report you to The Society Against Inhumane or Cruel Abuse of Colons


Gosh you are right : Im guilty as charged : gonna try make some edits to improve that : 😂

code of conduct - report abuse