Posted on August 18, 2022

Why I Won’t Use Clojure in Production Again

Skip to the meat of it if you don’t want to read all this stuff at the top

Preamble

This is a summary of why I don’t want to use Clojure professionally again, and why I don’t think others–who care about the things I care about–should either. I will probably just point folks at this answer in the future if I somehow decide to put my foot in my mouth and say anything negative about Clojure (and ClojureScript, but assume I mean both any time I mention Clojure going forward) again in public.

To save us both some frustration: if you send me a response to this I will likely ignore it, especially if it is a rebuttal to this. This post contains my opinion based on my experience, and given what I know now, it’s probably not going to change.

Some background context: I have been a web developer almost my entire career (24 years and counting). I used Clojure for about 8-9 years across three different companies. None of them were much bigger than 20-50 people by the time I left, as best as I can recall. Other than Clojure I have used Ruby (on Rails), Perl, and a bit of both Python and Java in professional contexts (and JavaScript almost everywhere I’ve been, although I’ve always been a mediocre JS programmer…and more languages I’m leaving out because my experience with those has been neglible).

Other than where I used Clojure, I have worked mostly in small organizations, but I was once at a large (tens of thousands of employees) company, and I worked in academic institutions twice. I am currently working at a small (~35 person) company that uses Haskell, PureScript, and Ruby on Rails together to support a web application with more than a million users. The last time I used Clojure was about a year and a half ago.

A lot of my points are framed in terms of static vs. dynamically-typed (a.k.a. unityped) languages, because at this point I think type systems are fundamental to writing coherent code. However, this post does not constitute an assertion that statically-typed languages are without tradeoffs or consistently easy to use in professional contexts–nor are they a monolith. The most I will assert is that statically-typed languages with decent type systems make maintenance far easier, which, at this point in my career, is one of the most important aspects of evaluating a programming language and everything it brings to the table–most of my time professionally has been spent supporting codebases written by other people; I don’t get to do a lot of greenfield work.

It’s also worth noting that a lot of the reasons I give for not wanting to use Clojure again could be applied to most any dynamically-typed language, but some things are specific to Clojure.

With That Out of the Way

Here’s why I don’t want to use Clojure professionally again:

In Conclusion

There’s more I could say, probably increasing in subjectivity the more I list, but I think those are the big ones. Obviously some are more significant than others, but taken together they resulted in all the codebases I worked on turning into tar pits of fiddly map and vector munging through arbitrary pipelines once the teams got to a certain size, with increasing amounts of breakage at runtime.

None of this means that you can’t write production code successfully with Clojure: all the teams I was on certainly did, even while it was increasingly painful and hard to scale as time went on. And, as I said above, a lot of these problems are the same problems you see with any dynamically-typed language past a certain scale.

I also suspect that if you have strong enough and mature enough leadership at the top of the technical hierarchy, a lot of these problems can be mitigated through top-down discipline and enforcing convention, which is certainly a consistent talking point for Mr. Hickey, although I’m not sure he means it in exactly this sense. But I also suspect that Clojure attracts a certain type of programmer, for whom the call to I-want-to-express-myself-ism is stronger than respecting the needs of the organization and their technical colleagues: I saw a lot of re-introduced, unnecessary solutions to the same problems that had already been solved over and over in the Clojure codebases I worked on over the years (and probably introduced some myself before I grew up). But again, none of this is unique to Clojure.

I also think Clojure really does have a lot of nice features–the immutable data structures are quite nice, and I think the syntax for those is really smart, violation-of-Lisp-purity be damned. Multimethods are excellent, and protocols are way underused. I thought core.async was pretty neat when it came out, and I always thought HoneySQL (I know, these are both libraries, not language features) in particular was one of the nicest ways to provide DB integration in any language I’d seen. I’m sure there’s more I’m forgetting.

But, I won’t use it again professionally.