From Node.js to Go

Last month Scaledrone migrated all websocket servers from Node.js to Go. We are a realtime messaging company so using the best possible websocket solution is vital to us.

We started playing around with Go because the memory required per customer was very high. In the end we got more than we asked for as Go servers use a third of the memory that our Node.js servers did. In addition to the memory usage lowering, both response and connections times were reduced significantly.

Node.js vs Go

Performance

Node.js uses an event-driven, non-blocking I/O model which is a double-edged sword. On one side, it makes programming a breeze since you don't have to worry about concurrency at all. On the other side, both JavaScript and Node.js set limits to performance. Based on our experience the statically typed and concurrent Go is about 3 times faster and more lightweight than Node.js in a production environment. Not to say that Node.js is slow, it's fast enough for most use cases but when you do hit a limit Go can still go a long way.

Ease of use

I found Node.js a much simpler platform to use, mainly because there is no worrying about concurrency. While Go does provide some elegant patterns for dealing with concurrency you still have to take it into consideration as if you were writing any other concurrent language.

Ecosystem

Both platforms have pretty active and growing ecosystems but as Node.js has been around the block longer it boasts more than double the modules. On some occasions I found no open source packages for Go even though there were multiple alternatives for Node.js.

Image from modulecounts.com

Another thing I found bothersome were the generated GoDoc pages. They were ordinarily not as easy to understand as hand written Node.js GitHub readme pages and came with very few, if any, examples.

Conclusion

Both platforms have their strong suits. While I find Node.js more fun to use I cannot deny that migrating our most performance critical service to Go has given us a lot more breathing room.

I recommend Node.js for those who don't have to deal with hundreds of thousands or millions of concurrent connections and Go for those who do.

Notes

Go has two very popular websocket packages. x/net/websocket which is bundled with Go itself and gorilla/websocket which is a third party package. We learned the hard way that x/net/websocket is missing a lot of features and not stable enough for production use. I recommend using gorilla/websocket.

pprof is an awesome tool to tracking memory leaks in Go. This made tracking leaks in Go much easier than in Node.js.