[HN Gopher] Clojuring the web application stack: Meditation One
       ___________________________________________________________________
        
       Clojuring the web application stack: Meditation One
        
       Author : adityaathalye
       Score  : 149 points
       Date   : 2025-05-20 13:15 UTC (1 days ago)
        
 (HTM) web link (www.evalapply.org)
 (TXT) w3m dump (www.evalapply.org)
        
       | adityaathalye wrote:
       | The ongoing discussion for Biff [1] prompted me to re-share my
       | post because I'd like more people to understand this "other way".
       | Outside Clojureville, it is _not_ obvious most of these Clojure
       | "frameworks" are _not_ monoliths.
       | 
       | The consummate Clojurist's _default_ (and very normal-feeling
       | way) to build a web application (or any application for that
       | matter) is to roll their own web stack from production-grade
       | libraries.
       | 
       | Of course, this state of affairs is a double-edged sword, just
       | like is true for traditional web frameworks. In my post, I try to
       | go into the whys and the wherefores, building upward from first
       | principles.
       | 
       | [1] Biff - a batteries-included web framework for Clojure
       | https://news.ycombinator.com/item?id=44037426
        
         | andersmurphy wrote:
         | A fantastic post! Enjoyed re-reading it.
         | 
         | I'd say the nice thing with the Clojure way of building your
         | own stack is it becomes quite easy to swap parts out. On a
         | previous project we swapped out our web server three different
         | times with minimal changes (jetty -> aleph -> httpkit) as for
         | the most part they all shared the same interface.
         | 
         | After a while you get good at seeing where you want things to
         | be configurable and where you don't. It also gives you the
         | confidence to roll your own micro stack/framework which means
         | you are not dependent on third party aggregates to adopt new
         | features.
        
           | adityaathalye wrote:
           | Thank you for the kind appreciation. Made my day :)
           | 
           | Yes; next to the sheer stability of parts, their fungibility
           | is a business-critical feature of the Clojure ecosystem. Of
           | course said fungibility does not magically manifest. However
           | the effort to get there is "not much", I'd say. The use of
           | "system" libraries, with some well-reasoned module design
           | brings it pretty close to magic.
           | 
           | As in the post, a fungible, production-grade part can be just
           | a multimethod (e.g. the router in the post). Why? Because
           | "production" comes in all sizes. A small SaaS with a few
           | hundred customers may chug along happily with a bunch of
           | functions.
        
             | yakshaving_jgt wrote:
             | This suggests to me that "production grade" isn't much of a
             | qualifier at all then.
             | 
             | You could just as well say that PHP has "production grade"
             | functions.
        
               | adityaathalye wrote:
               | Hm, I'm saying _a given_ function _can be_ production
               | grade. I 'm _not_ saying _all_ functions are production-
               | grade. Also, I 'm saying production comes in all sizes.
               | If your micro-SaaS app gives you a livelihood, that's
               | hella production --- real skin in game, real stakes in
               | ground.
               | 
               | To analogise further...
               | 
               | - HackerNews is a "production" system, you would agree.
               | Back in 2015, it was still true. Are flat files a
               | "production grade" primary data storage choice? [1]
               | 
               | - Suppose your production service transacts a million
               | requests an hour (say it is a short-link maker). Further,
               | let's say it has only a handful of API endpoints. Do you
               | really need a whole routing library for that, if a single
               | multimethod does exactly what you need, correctly?
               | 
               | etc...
               | 
               | [1] https://news.ycombinator.com/item?id=9990630
               | 
               | (edit: add reference for flat file storage)
        
               | yakshaving_jgt wrote:
               | Right. And what I'm saying is that if "production grade"
               | means all of these things, then it's not a very
               | meaningful qualifier.
               | 
               | My personal site is statically generated -- it's just a
               | bunch of HTML files and some CSS. Do you not think it
               | would be a bit pretentious of me to describe that as
               | "production grade"?
               | 
               | If "production grade" simply means fit for purpose, then
               | given the GP commenter's reason for their initial web
               | server swap, wouldn't you say by definition that jetty is
               | not production grade, since it doesn't (didn't?) support
               | SSE?
        
               | adityaathalye wrote:
               | I agree with you... "production grade" is in fact a
               | meaningless term without saying what grade one's
               | production needs to be.
               | 
               | A static site that _serves_ is most definitely a
               | production system. Perhaps one that could scale in
               | traffic almost without end.
               | 
               | evalapply.org gets (to my continued amazement) 20K+
               | unique visitors a month when it's business as usual. On a
               | busy HN day, it's easily that much in hours. I don't have
               | to think about "scaling problems". I don't have one.
               | 
               | I'm being the realest real with you.
        
           | yakshaving_jgt wrote:
           | > On a previous project we swapped out our web server three
           | different times
           | 
           | Why is this desirable?
           | 
           | On all my projects over the past 10 years, I've swapped out
           | the web server exactly zero times because the one I have
           | works just fine. The parent comment describes these
           | components as "production grade", but then if that's the
           | case, what could be the reason for swapping them out other
           | than self-indulgence?
        
             | andersmurphy wrote:
             | It's not. But, the fact that we could and it was straight
             | forward still amazes me.
             | 
             | In our case the first time we needed to, we needed SSE and
             | at the time there was no ring-jetty async interface (it's a
             | long time ago so I'm forgetting the details) so we moved to
             | aleph. Much later, we wanted to try out http-kit (self-
             | indulgence) as we were operating behind a proxy anyway for
             | performance reasons and it made a significant difference.
             | 
             | If we'd just started with http-kit that would have been
             | fine. I guess it comes down to what features you need.
             | 
             | Also I 100% agree it's something ideally you would want to
             | avoid a in the case of databases for example so much
             | performance is left on the table because for some reason we
             | want to be able to swap between SQLite, postgres and mySQL.
             | Which in practice you never want to do.
        
               | KingMob wrote:
               | As the former maintainer of Aleph, I'm very surprised you
               | ran into a situation where http-kit was faster. Or do you
               | mean it was just preferable to develop for?
        
             | adityaathalye wrote:
             | > Why is this desirable?
             | 
             | Generally, yes one would not want to swap out their web
             | server willy-nilly...
             | 
             | Yet, this is one of those "YAGNI in 99% of your use cases",
             | but when that 1% use case arises, a server swap would be
             | far more desirable than a whole framework shift.
             | 
             | So while self-indulgence can certainly be a motive (and why
             | not? as long as everyone's having a good time), may I offer
             | a few more charitable reasons for this:
             | 
             | - programming API ergonomics
             | 
             | - performance
             | 
             | - application runtime model (servlets -> embedded server)
             | 
             | - security model
             | 
             | - application server features (websockets, comet?)
             | 
             | - binary size
             | 
             | - server configuration niceties
             | 
             | etc...
             | 
             | That said, a developer only has flexibility if it is built
             | in from the get go.
             | 
             | A counterfactual would be to consider the set of developers
             | who have had to put in ugly hacks because they can't just
             | rip the web server out of the framework of choice they are
             | locked into.
             | 
             | (edit: bullet list formatting)
        
               | yakshaving_jgt wrote:
               | > and why not?
               | 
               | Because I pay the people who work for me.
        
               | adityaathalye wrote:
               | Well, if you're paying, you certainly get to set the
               | rules. No self-indulgence, then. The other reasons I
               | enumerated may still hold.
        
           | gehrman wrote:
           | Your comment reminded me of this talk
           | https://www.youtube.com/watch?v=MZy-SNswH2E.
           | 
           | The part about building just the functionality you need,
           | using the bare minimum libraries etc stuck out.
        
       | elchief wrote:
       | Metabase is written in clojure, if you want to see the source
       | code of a large web app
       | 
       | https://github.com/metabase/metabase
        
         | adityaathalye wrote:
         | +1
         | 
         | NASA's Common Metadata Repository is worth exploring too
         | https://github.com/nasa/Common-Metadata-Repository
         | 
         | It is a neat example of how an org can structure and manage
         | multiple projects and services in a single git repository.
         | They've use Leiningen to achieve their objective.
         | 
         | > The Common Metadata Repository (CMR) is an earth science
         | metadata repository for NASA EOSDIS data. The CMR Search API
         | provides access to this metadata.
         | 
         | > Building and Running the CMR
         | 
         | > The CMR is a system consisting of many services. The services
         | can run individually or in a single process. Running in a
         | single process makes local development easier because it avoids
         | having to start many different processes. The sections below
         | contain instructions for running the CMR as a single process or
         | as many processes.
         | 
         | (edit: add relevant context for quick reference)
        
           | geokon wrote:
           | wow I had no idea Nasa used Clojure. I do remmeber them using
           | quite a bit of Java so it's not terribly surprising
        
           | 90s_dev wrote:
           | Sorry, what? Did you just say _NASA uses Clojure_?? That must
           | be a pretty big honor for Rich.
        
             | adityaathalye wrote:
             | Clojure(Script) apps and systems exist at a bunch of
             | household name places.
             | 
             | - Clojure: https://clojure.org/community/companies
             | 
             | - ClojureScript:
             | https://clojurescript.org/community/companies
             | 
             | Also, a few case studies may interest you:
             | https://clojure.org/community/success_stories and community
             | stories: https://clojure.org/community/community_stories
        
         | ramirond wrote:
         | Thanks for the shout! I recommend this video about our Clojure
         | journey: https://www.youtube.com/watch?v=vUe3slLHk20
         | 
         | We are also hiring Clojure devs: https://www.metabase.com/jobs
        
         | lelag wrote:
         | The metabase "backend" is written in clojure.
         | 
         | The web frontend is written in TypeScript/React.
        
       | librasteve wrote:
       | a very lyrical post, i will reread at my leisure and try to apply
       | the lessons to https://harcstack.org
       | 
       | that's HTMX, Air, Red & Cro btw
       | 
       | that said ... I am a true believer in HTMX for the right amount
       | of UX dynamism and I don't initially get solves that piece
        
         | andersmurphy wrote:
         | If you need the next level of UX dynamism and or realtime
         | updates and or multiplayer. I've handled a billion
         | checkboxes[1] with clojure, sqlite and datastar (realtime
         | hypermedia) just fine.
         | 
         | [1] https://checkboxes.andersmurphy.com
        
           | librasteve wrote:
           | yeah the datastar guys are often on the HTMX discord - guess
           | that's an option for that - tx!
        
         | adityaathalye wrote:
         | Thank you for the kind appreciation.
         | 
         | Following writing advice or post structuring guidelines is not
         | in my job description at evalapply.org Luckily, Michael
         | Hamburger offered a legitimate excuse in his classic (so I'm
         | told) essay, _" An Essay About Essays"_:
         | https://substack.com/@bombaylitmag/p-162583447
        
       | wink wrote:
       | The problem with this approach is that (esp. for hobby projects)
       | updating stuff is a bit tedious. Let's say you have a relatively
       | bare bones project in Rails or a PHP framework you have a couple
       | of dependencies that people usually use together, so upgrading
       | can be quick and painless.
       | 
       | I've now had it several times in the years-long lifespan of small
       | clojure web projects that people have moved on and the thing
       | (framework-ish) basically doesn't exist anymore and going by the
       | issues it only had like 10 users in the first place.
       | 
       | It's not the end of the world, and fortunately there's not a lot
       | of needless churn, but I guess I would prefer to have this "I am
       | trusting project x and I only have to care about their releases
       | (pre-testing all the moving parts) and then my 5 dependencies"
       | and instead I have 20 dependencies/moving parts for my web app.
       | 
       | Yes, I'm lazy and I don't think it's a problem in an env where
       | you have a proper dev workflow anyway.
        
         | wild_egg wrote:
         | > updating stuff is a bit tedious
         | 
         | How often do you have to do that though? I was under the
         | impression that Clojure was a bit like CL in that old code will
         | keep working basically forever. Unless there are new features
         | you need, you just leave most libs alone to do their job.
        
         | epgui wrote:
         | This can be a culture shock for people coming from places like
         | ruby, python, javascript... But a lot of clojure libraries are
         | actually just "finished", they're not abandoned.
        
       ___________________________________________________________________
       (page generated 2025-05-21 23:02 UTC)