HackerReposA FIELD GUIDE TO OPEN SOURCE
ProSponsor the shelf♧ 0
← Back to top all-time
clj-commons
aleph
Clojure2011–2023
clj-commons / aleph

aleph

Asynchronous streaming communication for Clojure - web server, web client, and raw TCP/UDP

9Distinct people
11Mentions
0Explicit recommenders
2.6KGitHub stars
REPOSITORY AT A GLANCE

What to know before exploring

What it is

Asynchronous streaming communication for Clojure - web server, web client, and raw TCP/UDP

GitHub

Where it is used

No documented product use has been verified yet.

What people are saying

No recommendation phrase was found in the indexed comments.

No classified warning is attached to this page. Read the discussions before treating silence as approval.

Also in these discussions

No other repository is repeatedly linked in the same discussions.

This week on Hacker News

Nov 7–Nov 14 UTC · Direct repository links and separately labeled related project stories. Indexed through 11/14/2026, 3:56:07 PM UTC.

No direct repository links were found in the indexed HN discussions over the past seven days. Older discussions are available below.

Mentions over time

HN mentions by year11 dated mentions

Observed mentions: 2011-02-10 23:00:35 UTC to 2023-08-10 15:09:39 UTC.

01232011-01-01 00:00:00 UTC to 2012-01-01 00:00:00 UTC (exclusive): 2 mentions; 0 submissions, 2 comments20112012-01-01 00:00:00 UTC to 2013-01-01 00:00:00 UTC (exclusive): 2 mentions; 0 submissions, 2 comments2013-01-01 00:00:00 UTC to 2014-01-01 00:00:00 UTC (exclusive): 2 mentions; 0 submissions, 2 comments2014-01-01 00:00:00 UTC to 2015-01-01 00:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments2015-01-01 00:00:00 UTC to 2016-01-01 00:00:00 UTC (exclusive): 1 mentions; 0 submissions, 1 comments2016-01-01 00:00:00 UTC to 2017-01-01 00:00:00 UTC (exclusive): 3 mentions; 0 submissions, 3 comments2017-01-01 00:00:00 UTC to 2018-01-01 00:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments20172018-01-01 00:00:00 UTC to 2019-01-01 00:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments2019-01-01 00:00:00 UTC to 2020-01-01 00:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments2020-01-01 00:00:00 UTC to 2021-01-01 00:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments2021-01-01 00:00:00 UTC to 2022-01-01 00:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments2022-01-01 00:00:00 UTC to 2023-01-01 00:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments2023-01-01 00:00:00 UTC to 2024-01-01 00:00:00 UTC (exclusive): 1 mentions; 0 submissions, 1 comments2023

Counts come from the repository’s dated source evidence. Index cutoff: 2026-11-02 08:16:59 UTC.

View mention counts and date ranges
UTC ranges include their start and exclude their end. Select a period to filter the source evidence.
PeriodStart (UTC)End (exclusive, UTC)MentionsSubmissionsComments
20112011-01-01 00:00:00 UTC2012-01-01 00:00:00 UTC202
20122012-01-01 00:00:00 UTC2013-01-01 00:00:00 UTC202
20132013-01-01 00:00:00 UTC2014-01-01 00:00:00 UTC202
20142014-01-01 00:00:00 UTC2015-01-01 00:00:00 UTC000
20152015-01-01 00:00:00 UTC2016-01-01 00:00:00 UTC101
20162016-01-01 00:00:00 UTC2017-01-01 00:00:00 UTC303
20172017-01-01 00:00:00 UTC2018-01-01 00:00:00 UTC000
20182018-01-01 00:00:00 UTC2019-01-01 00:00:00 UTC000
20192019-01-01 00:00:00 UTC2020-01-01 00:00:00 UTC000
20202020-01-01 00:00:00 UTC2021-01-01 00:00:00 UTC000
20212021-01-01 00:00:00 UTC2022-01-01 00:00:00 UTC000
20222022-01-01 00:00:00 UTC2023-01-01 00:00:00 UTC000
20232023-01-01 00:00:00 UTC2024-01-01 00:00:00 UTC101

What Hacker News says

11 sources
The Clojure's approach is to favour libraries over frameworks. We use Clojure on various style of applications (mainly web and API based), hosted on widespread infrastructure technologies of Cloud Providers (Kubernetes, PostgreSQL, Kafka, etc.) and it's a breeze: here are our reasons for choosing Clojure https://defsquare.com/blog/why-we-bet-on-clojure If you want to look at libraries where some people have settled, here are our _opinionated_ takes on libraries that we use on almost every project: - HTTP: Ring is the de facto way to manage HTTP request (see https://github.com/ring-clojure/ring/wiki/Concepts) supplemented with various "Middlewares" for web-related concerns (security, logging, content encoding, etc. see https://github.com/ring-clojure/ring/wiki/Standard-middlewar...). Jetty and Aleph are common web servers (and https://gith
Read the rest
ub.com/clj-commons/aleph) that implement Ring interface. - Routing: Reitit (https://github.com/metosin/reitit) - Single-Page App: shadow-cljs for the build concerns (https://github.com/thheller/shadow-cljs), Reagent with Re-frame for complex/large app (https://reagent-project.github.io and https://github.com/day8/re-frame). Even if we now prefer using HTMX (https://htmx.org) and server-side rendering (Hiccup way of manipulating HTML is just amazing, https://github.com/weavejester/hiccup). - Schema management: Malli (https://github.com/metosin/malli) - Lifecycle management: Mount, Integrant or Component (https://github.com/tolitius/mount https://github.com/weavejester/integrant and https://github.com/stuartsierra/component) - Config management: Aero (https://github.com/juxt/aero) and environ (https://github.com/weavejester/environ) - Log: μ/log (https://github.com/BrunoBonacci/mulog) - Time: https://github.com/juxt/tick - Testing: https://clojure.github.io/clojure/clojure.test-api.html and Kaocha for the runner (https://github.com/lambdaisland/kaocha). - Package and project management: tools.deps is simple and powerful (https://clojure.org/guides/deps_and_cli) For infrastructure stuff (PostgreSQL, Keycloak, Solr, Kafka, etc.), just wrapping the underlying Java library or driver is often enough, and there are lots of wrappers for easing the integration. And we implement Hexagonal architecture style to put all of that in place. Don't be afraid a libraries not moving a lot recently, it's a sign that the library is mature and battle-tested. Clojure is a joy to use every day :)
In A History of Clojure (2020) [pdf]
Can't agree more. I feel like the reason why a lot of Lispers back in the day ended up re-inventing the wheel is not because of Lisp's "dark, seducing power" but simply because the tools and solutions just weren't there yet. For example, if it wasn't for the existing JVM ecosystem of tools and libraries, I would probably end up creating my own undocumented, unportable, bug-ridden implementation of 80% of Netty. Instead, I just use https://github.com/ztellman/aleph
In The Lisp Curse (2011)
Thanks. I think Erlang is the grandfather of languages using the actor pattern and at the same time Joe realized that POSIX threads does not belong to business logic code and it can be done without leaking the number of actual OS threads to the user's codebase. On the top of that Joe also implemented the message passing to avoid the shared memory that is a serious problem from the safety point of view for applications with threads. One thread can take down the entire process execution. Addressing these in Erlang made it possible to write the first commercial system with extra high availability and fault tolerance. JVM is obviously great a VM, and Scala brings most of the Erlang (and many other languages) features to the table. I am not sure about the fault tolerance. I need to look into how Akka implements the actors. > Concurrency means
Read the rest
synchronizing and sending messages between > processes. I think in Erlang you can do only async sending and when the receiving process wakes up it gets it through one of the means you mentioned. http://bartoszmilewski.com/2009/02/10/message-passing-sync-o... > Erlang can't cope with this load btw. This is what I am curious about. I have seen only one big system written in Erlang that was massive big. WhatsApp was also running in Erlang and they achieved something like 1M connection/server. That was impressive. I am wondering how could you do that with Akka? > https://github.com/puniverse/quasar I am following the development of these, starting to use it in Clojure soon, I am curious how it works out. Personally I prefer Aleph on the JVM for Clojure projects but wanna see what is happening in Quasar & co. https://github.com/ztellman/aleph
In OCaml 4.03 will, “if all goes well”, support multicore
I don't have an answer for you, but for the last year I have been learning Clojure, and I have found it fascinating. I do not think this will satisfy you, but I would like to share some of the things that I find interesting about Clojure. Lately I've been studying the source code of Aleph, a web server written by Zach Tellman. Zach is a very smart guy, and reading his source code is an education (I've actually found this true of the majority of Clojure projects: the quality of the code is very good, and Clojure is the only language I've worked with so far where I have been able to learn so much reading the source code of the 3rd party libraries that I rely on). Let's start with an interesting comment about Java, on StackOverflow: Why doesn't more Java code use PipedInputStream / PipedOutputStream? http://stackoverflow.com/questions/484119
Read the rest
/why-doesnt-more-ja... In response to that question, matt_b suggests this is part of the reason why people don't use pipedinputstream or pipedoutputstream: "Typically, data is read from a PipedInputStream object by one thread and data is written to the corresponding PipedOutputStream by some other thread. Attempting to use both objects from a single thread is not recommended, as it may deadlock the thread." So now, look at how PipedInputStream and PipedOutputStream are used in Aleph: https://github.com/ztellman/aleph/blob/perf/src/aleph/format... In particular, look at this function: (defn channel->input-stream "Consumes messages from a channel that emits bytes, and feeds them into an InputStream." ([ch] (channel->input-stream ch "utf-8")) ([ch charset] (let [out (PipedOutputStream.) in (PipedInputStream. out 16384) bytes (map* #(bytes->byte-array % charset) ch)] (future (try (loop [] (when-let [msg @(read-channel* bytes :on-drained nil)] (.write out ^bytes msg) (recur))) (finally (.close out)))) in))) I think this is very clean. He uses (future) to put the PipedOutputStream on its own thread, meanwhile he returns a PipedInputStream to whoever is calling this function. This is a good use of PipedInputStream/PipedOutputStream, and he's ensured they run in separate threads, which answers the concern that matt_b raised on StackOverflow. On a different subject, I have learned a new style of programming by using closures in a functional language. Maybe I am a bit stupid, but it took me a long time before I began to realize how useful closures are. My only other exposure to closures was with Ruby and Javascript, but I never did concurrent programming with Ruby or Javascript, and it seems to me the greatest use of closures is when you are dealing with a lot of threads. When I first started writing Clojure code, I did not use closures at all. I wrote some clumsy code. For instance, I wrote a function that got some data from the database, and I wrote another function that stored that data in a hashmap in memory (using the memory as a cache) and I wrote another function that would check the hashmap for the data, before making the call to the database, and then I wrote another function that ran every 15 minutes and erased items in the hashmap, thus invalidating the cache. But then I realized I could combine several of these operations by creating a closure at the moment that I store data in the hashmap: the closure could call Thread.sleep(900000) and then delete the data from the hashmap. I found it convenient to create the closure while I was storing the data in the hashmap as, at that moment, I have all the information I need, including the key with which that data is being stored. Then I push the closure onto a queue and it gets processed in 15 minutes. This simplifies things quite a bit. Again, Zach Tellman's code has been educating me about how powerful closures can be in the context of concurrent programming. Look here: https://github.com/ztellman/aleph/blob/perf/src/aleph/http.c... And look especially at this function: (defn wrap-ring-handler "Takes a normal Ring handler, and turns it into a handler that can be consumed by Aleph's start-http-server. If the Ring handler returns an async-promise, this will be handled properly and sent along as a long-poll response whenever it is realized. This should be the outermost middleware around your function. To use an Aleph handler at a particular endpoint within the scope of this middleware, use wrap-aleph-handler." [f] (fn [ch request] (run-pipeline request {:error-handler (fn [ex] (error ch ex))} ;; call into handler (fn [{:keys [body content-type character-encoding] :as request}] (if (channel? body) (if (options/channel-ring-requests? request) ;; leave channels as is (f (assoc request ::channel ch)) ;; move onto another thread, since there will be blocking reads (task "input-stream-reader" (f (assoc request ::channel ch :body (formats/channel->input-stream body character-encoding))))) (f (assoc request ::channel ch :body (formats/bytes->input-stream body character-encoding))))) ;; send response (fn [response] (when-not (::ignore response) (enqueue ch response)))))) Here you have a function that returns a function that returns another function. The first returned function calls (run-pipeline) and gives (run-pipeline) a closure that will be called later, but with data that we have right now, in this context. You are asking why functional programming is a big deal. I'm sure different people will have different answers. I think the difficulty in answering is that there is no one thing that by itself makes an answer, rather, it is a whole series of things that combine in powerful ways. For me, the immutable data structures of Clojure are an education. I have learned a lot. I think using closures in the context of concurrent programming could be an absolute nightmare, if it was not for the safety offered by immutable data structures. And yet, I don't think immutable data structures are a big deal by themselves, nor do I think that closures are a big deal by themselves, nor do I think concurrency is a big deal by itself. Only when I look at the combination of these 3 do I find myself enlightened, like I've just discovered a whole new level of programming, a level of power I have never felt in any other language. A final note: Adam Bard has a blog post "Effortless async by design" in which he says "I dare you to find a thread-safer language. Well, maybe Erlang." And then he also uses some code from Zach Tellman to demonstrate what he means. Bard's post is worth a read: http://adambard.com/blog/why-clojure-part-2-async-magic/ I could list a lot of things that seem to me very powerful about the coding style I've learned this last year: composability, currying, closures, immutable data structures, thread-safe, etc. But I think descriptions like that tend to be a bunch of meaningless buzz words until you've dived in deep enough to see how they all interact with each other. Because its the interaction of these features that is really powerful, not any of them alone.
In Why functional programming?

MAKE YOURSELF AT HOME

A few shortcuts

/
Search the collection
?
Open this guide
Esc
Close dialogs and navigation

Your saved repositories and interests stay in this browser.