Is Golang good for real-time services? Should I choose Node.js instead?

It depends on what you mean by "real-time"

  • Chats, collaboration boards, streaming? Definitely yes, Go will fit perfectly!
  • Stock exchange trading and similar? maybe, needs testing, Go could be sufficient but it really depends on what latency tolerances we’re talking about.
  • Fighter-jet sensors, 3D VR rendering and similar? Definitely no, that’s where Go’s garbage collection and poor compiler optimizations (compared to C) are usually not an option.

Should I choose Node.js instead?
I don’t think so, and I’ve described why in another blog post. There are several problems with Node:

  • Node is very unpredictable in terms of performance due to dynamicity and JIT compilation. Go is statically typed and compiles to machine code ahead of time making it very predictable. You can even just take a look at the output assembly to find out what’s wrong if needed.
  • Node will usually be slower than Go in general. For example, there’s no integer types in JavaScript, just “numbers”. Numbers are 64-bit floating point numbers (IEEE 754). Computations on integers are usually way faster and I’m not sure V8 is able to optimize this at all. Go, however, supports both 32- and 64-bit integers and is able to produce fast executables (not as fast as C/C++/Rust, but usually faster than V8). In computing, anything dynamic will always add runtime cost (like dynamic vs pre-baked lighting in 3D graphics).
  • Node won’t make it easy to find your performance problems. First of all - JavaScript is extremely difficult to benchmark correctly, Go, however, supports benchmarking natively through pkg/testing and go test. Go also has a tracer and pprof built-in because it’s designed with development of high-performance software in mind. JavaScript was never designed to be used as a server-side programming language.
  • Multi-threading… again, JavaScript was never designed to be a language with multi-threading capabilities. Go was deliberately designed to make multi-threaded concurrency easier than the traditional threading model. There are several ways to make a Node-powered service use multi-core CPUs (like workers and clustering) but the only advantage compared to Go is that JavaScript is somewhat safer in terms of memory management because in Go you can easily shoot yourself in the foot with data races. Luckily we do have a data race detector built-in to Go so it’s not that much of a problem, you’ll just have to acquire a few multi-threaded programming skills. Go will do much better at utilizing modern multi-core systems because there’s no event loop but a built-in user space scheduler and goroutines utilizing all CPU cores whenever possible.

I’m not trying to say “Node is bad, you shouldn’t use it for real-time systems at all”, it might actually do surprisingly well when there’s only little JavaScript and things like uwebsockets backing it, but I really feel much more confident with Go because I know - if there’s ever a performance related problem - I’ll find it quickly using the tracer and profiler, I’ll fix it easily and prove it’s faster with actual benchmarks. I can even check what string concatenation method is the fastest in the nano-seconds range which is considered “micro-benchmarking” and almost undoable in JavaScript.

There’s always an option to write V8 modules in C++ and use them from JavaScript but it’s much more difficult than it seems and you’ll be dividing your code-base into 2 languages (2 ecosystems, essentially) which is far from good.

If you want to get new posts, make sure to subscribe to Value In Brief by Email.