Running a quick `cloc` on my company's codebase shows we have about 40,000 lines of production Clojure code. Most of it supports a couple or three web apps.

For me, deploying production Clojure has been fantastic. Is it a panacea? No, definitely not. If you like typing, stay clear. Spec is cool. Very cool. But it's not static typing. And, if thinking in s-expressions doesn't come natural within a reasonable amount of time, consider Elixir instead.

I do, however, prefer dynamic languages, and I frankly LOVE LISP, so it suits me. The JVM has never been a hindrance; in fact, I appreciate the comfort of knowing there's a deep ecosystem of Java that can be tapped, which I have (easily!), in extreme situations like PDF manipulation, or whatever.

Clojure also meets its performance claims – it's fast. My company doesn't carry behemoth level request loads, so I can hardly provide impressive metrics, but decently considered code will execute plenty fast with room to spare. Although we're light users, Clojure's concurrency features are nice too. For most async stuff, forget background job processes – use futures. core.async is cool, but overkill for most web stuff. We've built a bare-minimum job processor for must-finish tasks, but that got done in about 100 lines of code.

My major piece of advice, if you plan to use Clojure for the web, is to get comfortable building custom homes for your web apps. Not in the sense that you'll HTTP stuff from scratch – no, there are excellent libraries for all of the critical stuff. Redis, AMQP, ORMs and SQL libraries of all flavors, caching, routers – everything you'd want for the web is there.

Just be mindful of the fact that your web app will look nothing like your neighbor's. There are NO integrated web frameworks. Not successful ones, at least.

And, I think, for good reason. Clojure is not the average Clojure developer's first language. There was a significant influx of Rails devs several years ago. Clojure is bereft of black magic. A lot of Clojure libraries are so small, and so sharp, you can easily unearth their features by reading a few source files. Which, of course, is good and bad. The side effect, being, very little of the documentation in the community is geared towards beginner programmers. Starting out, my single biggest frustration in the Clojure community was the knowledge library authors assumed you brought to the library.

I'd compare the ecosystem – loosely – to NPM's, but without the cruft. You build your web app up from small components (Component and Mount are awesome!... eh, except for the fact that they are, as are so many Clojure things, original material that takes time to digest...) that easily fit together. It's a breath of fresh air knowing almost all libraries live in harmony.

So, the backend Clojure story, in my view, is great – if you don't mind being on your own once in a while.

The front-end story, however... well, is a mixed bag, I think. Yes, ClojureScript is making huge strides in being futuristic and compiling to negative kilobytes an' all. But some of its highest profile projects are sadly proving impenetrable. Om and Om.Next are total non-starters for small to mid-sized projects (YMMV) as their documentation is so beyond comprehensible. I _have_ made a real project in Om.Next – with tremendous effort – but I've been developing in Clojure for nearly five years. And, when you can't remember how something works a day after you wrote it... that's trouble.

If you want Clojure for the front-end (which we've dabbled in to a degree, but for our company, the return on beginner Javascript developers in React is still satisfyingly high), I'd recommend Reagent. Keep it simple.

Back to Clojure proper, one thing I enjoy immensely is seeing how far I can take a program in a single file. Not always practical, but it's fun knowing you can scan a file (often starting at the bottom) and quickly grok it. Do know, however, reading Clojure (or any LISP, that is) is sometimes harder than writing it, especially in a large codebase. It's here, I think, where statically typed languages have an edge on Clojure – refactoring is more dangerous: you can never fully tell the shape of data passing between functions.

Spec has helped, for sure. For simple, obvious tasks, take a risk. On mission-critical-can't-break-type stuff, however, you'll be grateful for spec. No, it's not the anxiety-free experience you hear about in Elm or Haskell, but geez, at least you can get fresh code working fast. It's here where I continue to believe dynamic languages like Clojure have a permanent place in history – solving problems iteratively, with little pomp and ceremony, without knowing the end from the beginning. And saying to yourself, "Yes, this works, and while not perfect, I made it quickly, and it's extensible and maintainable."

The most beautiful thing about writing a production app in Clojure is this: you can build a big app from tinier programs. I don't mean microservices. I mean small, easily divisible namespaces in a single project that talk to each other via messages. Like, really, you can easily treat separate namespaces as if they're different actors in a plug and play network.

A talk I heard recently (can't remember where) suggested writing your big program from small programs, small enough that any individual program can be rewritten in a week. Clojure does this for us. When I started out, being unfamiliar with functional paradigms in general, I brought a lot of tightly coupled OO practices that I had to unlearn. Unfortunately, "real world" Clojure tutorials are scarcer than they ought to be. But, unlike in my Ruby and Java days, there are _very few_ things that need to be completely rewritten in Clojure. The core language is simple enough that almost all Clojure code resembles itself.