cb codes

Node.js Vs. Clojure

Clojure vs Node.js Google Trends


I wrote an article that tried to compare Node.js and Clojure for web development in 2014. When I migrated my blog from Wordpress to Jekyll today, I deleted a lot of old posts, including the 2014 version of this one. I didn't feel like it was an honest and objective comparison. Also, since then I've gotten a much better understanding of the strengths of the Node.js and Clojure communities and ecosystems, so here are my thoughts now.

I moved from backend Clojure projects at work to working on a React/Redux frontend for one of the backends we buit in Clojure. While I don't have extensive production server-side javascript experience, I have dabbled in it in the past for side projects. My limited server-side javascript experience shouldn't be completely discounted yet, because I still feel that you can get value out of my commentary on the Node.js ecosystem.

The Web Framework Story

The first thing most people notice when they join the Clojure community coming from another language is that there are no web frameworks. No such thing.

You might consider Luminus to a framework of sorts. It even says on the homepage that it's a Clojure micro-framework! But really it's just a template for web applications in Clojure. It's a great starting point for beginners, but that doesn't make it a framework.

I define a framework to be like a shell. A shell that standardizes how things should be done and easily enables people to snap pieces they want in (for the general case). I'm sure somebody out there is already poking a holes at my definition, but hear me out.

The reason Ruby on Rails is a framework, other than it giving you everything and the kitchen sink, is because you can reasonably expect that people using Rails would also be using ActiveRecord, ActiveSupport, Rack, and ActiveWhateverElse.

What this enables is that other people can build on top of this expectation. For instance, the devise gem allows you to just easily drop form-based authentication into your application. You don't have to write functions that call your database and do the CRUD for your users. It just works for 90% of the use cases.

This is also why I think of Express.js as a micro-framework. It enables a similar story for authentication on the Node.js side with passport.js. The cool thing about passport.js is that there are 307 authentication strategies as of today that you can just snap in.

What about templating? In Rails it's usually as easy as dropping in another gem and renaming your files. In Express, you add another dependency and call a few functions to hook it up. Then you put your templates in a standard path and you're good to go.

In Clojure? You have to do a lot of work if you want to switch templating libraries halfway through. I'm not talking about changing your template/view code either. That's a given.

The work you have to do is due to how there's no standard interface to hook up your templating engines like in an actual web framework. Let's say you start out using hiccup for your templating. Hiccup templates are just Clojure datastructures, so they live in the src directory of your code.

Then it turns out the team of designers that just joined your team don't like and don't want to learn hiccup even though it's just HTML but simpler syntax. So you decide to switch to using Enlive. Or maybe moustache/handlebars. Anything to make the designers happy.

The work to switch your templating library can involve re-structuring the entire codebase. Remember, your hiccup templates live with your code! You have to figure out where to put your new templates (likely just on the classpath somewhere) and incorporate it into your code base without a standard interface to hook it in.

My Take On Frameworks

The Clojure community embraces tiny modular libraries to a fault. In my mind, there's a false dichotomy between going full monolith like Rails and composing each library yourself. It's not black and white like how most of the Clojure community makes it out to be.

I think the Node.js community almost gets the balance between full framework and tiny libraries right. Express.js doesn't give you everything and the kitchen sink. And everything is in its own module. If you need specific middleware, for instance form body parsing, you can include it and plug it in. And I think the key difference is that a framework gives you a standard to plug things in. Think Micro-USB. And having no frameworks at all reminds me of when we all had dumbphones and each phone had its own proprietary charger.

Performance and Speed

Clojure is faster than javascript at computationally intensive tasks thanks to the JVM. The question then is, do you need the speed that Clojure offers?

Check out the TechEmpower Benchmarks and make your own choices based on what workload fits your application the best.

One more thing to consider is that Node.js drops down to native C libraries to some of it's work like making requests. If your workload is primarily waiting on things to happen, it's something to also keep in mind.

How To Pick Between Clojure and Javascript

If you're building a website, Node.js is the right tool for that job. Due to lack of web frameworks, the server-side rendering, CRUD, type of web application is going to be slower in dev time to make in Clojure. That has been my experience 100% of the time. If you're going to do CRUD, don't reinvent the wheel. Use a framework.

If you're building a single page application, then you can use either Clojure or javascript. I would lean towards whichever language you build your backend in.

If you're building an API or service that isn't computationally intensive, like waiting on network calls, then Node.js is probably the right tool. Let's be honest. Most of the time spent in your web application is just waiting on a record from a database and sending it back to a user. Node's async by default is good for the majority of these cases.

If you're building building an API or service that isn't computationally intensive, but hate callbacks, then use Clojure and leverage core.async.

If you're building an API or service that is computationally intensive, like doing machine learning on a large dataset, then Clojure is the right tool.

If you need to leverage the JVM... then Clojure. Hadoop? Apache Spark? Parallel computing? Clojure is surely the tool here.

If you want to attract better engineers (on average) and retain more talent by spicing things up, then go Clojure.


Use the right tool for the job and what makes you and your team happiest. Iterate fast and most importantly, build something people want.