It’s right at the end of 2016 and I’ve leapt into a new startup as the only engineer. My first big decision is what technology stack to build our product with. I’ve picked nodejs and here is why.
This is the main reason, and one that’s almost always the best one when starting something from scratch. There’s lots of really interesting languages and frameworks out there. I’m really interested in functional programming and loved my time working in Ruby so Elixir and Clojure were two things that sprung to mind.
I’ve reached professional proficiency in a few languages now, so I don’t think it would take me long to get to grips with either of those. It’s not that simple though: all languages come with their own idioms, frameworks, package mangers, devtools and deployment issues. For Clojure, sure I can code LISP, but I know nothing about running the JVM in production.
Turns out I’m not Rich Hickey.
Sticking to what I know means that I don’t need to lose any precious time learning new tricks or troubleshooting problems of my own making due to not understanding the stack in depth. I cut out a big chunk of risk too. I know what I’m getting myself into. When doing an early stage startup there will be so much that you can’t know — it makes sense to cling to what little you do.
While not quite as productive as Ruby on Rails, you can still move very quickly. There is a module for pretty much anything you can imagine for nodejs thanks to the amazing npm ecosystem. I’ll save time by using other people’s modules. Not all of them are very good but I can tolerate the odd shabby implementation for now. I will write my own later if and when I have problems that aren’t “Having no product” or “Having no customers”.
Nodejs is now mature and battle tested and is being used by a great many of big technology companies such as Netflix and Paypal. Even Microsoft are keen to join the party. This means that money is being spent on keeping it stable and making it better. I can be confident that it’s not going to be abandoned or neglected any time soon.
Back in 2007, Jeff Atwood wrote another of his influential blog posts. In it he coined a phrase:
Since 2007 this has only got more true. The way I like to think of it is this:
There’s other nice things, like being able to share code across the browser and the server. Something that reactjs makes reasonably straightforward.
Nodejs is plenty fast enough to scale pretty nicely, and when I have out grown it, I will be a long way from where I am now. This is a problem I would dearly love to have. When that day nears, it won’t be the end of the line for nodejs. I see it being a part of my system in perpetuity.
As I said, right now I want to keep things simple. This goes for my architecture too so my app will be a monolith for now. One codebase, one deployment, everything in one place. Microservices are a great solution for problems involving scale and complexity; For productivity, not so much. Time spent messing with service discovery, load balancing and the rest is time I’d rather be using to create product.
The monolith. It’s not very fashionable, but it is very simple.
One day though, my monolith will start to creak, some bits will be too slow and the whole thing will become unwieldy due to it’s sheer size. I’ve been at startups that got to this point with their Rails application. Attempts to extract functionality and encapsulate it out of process or fully distributed were successful, but brought substantial drawbacks. Ruby is single threaded and blocking. When a Rails app makes a call on the network, the whole thread waits for the response before doing anything else. The more services you add, the longer you wait.
This meant that in the transition period, things got pretty slow, and the further into the transition we went the worse it got. It also resulted in a near extinction of Ruby in the codebase. While Ruby and Rails enabled the team to move quickly in the early stages, later on Ruby didn’t seem the best choice for a distributed system. All the team’s Ruby knowledge was wasted post transition and it made the Rubyists sad.
With a nodejs system, things are a bit easier. While it is single threaded, it’s also asynchronous and non blocking. This means that while we wait for the network to do it’s thing other requests will be serviced. Adding distributed components does not destroy performance.
It take a a village of services to build a system. All safely behind a thin wall of nodejs.
I guess we will see over the coming years if I live to regret my decision. In the mean time, I’m also hiring the first member of my engineering team. So if you fancy hacking on nodejs, drop me a line: [email protected]