An HTTP/1.1, HTTP/2, HTTP/3 and WebSocket server for Clojure Ring handlers, with no dependency besides Clojure. The core is written in Java for Ring and runs on virtual threads.
Status: alpha. Option names and the API may still change between releases (see the changelog).
{:deps {com.s-exp/enso {:mvn/version "1.0.0-alphaN"}}}
HTTP/3 is optional. It needs a second artifact for your platform, which contains a JNI shim with libquiche linked in, so there is nothing to install on the system:
{:deps {com.s-exp/enso {:mvn/version "1.0.0-alphaN"}
com.s-exp/enso$linux-amd64 {:mvn/version "1.0.0-alphaN"}}}
Classifiers: linux-amd64, linux-arm64, linux-musl-amd64,
linux-musl-arm64, darwin-arm64.
(require '[s-exp.enso :as enso])
(def server
(enso/run-server (fn [req] {:status 200 :body "hello"})
{:port 8080}))
(enso/stop server)
With TLS, HTTP/2 and HTTP/3:
(enso/run-server handler
{:port 8443
:ssl-context ssl-context ; a javax.net.ssl.SSLContext
:http2 true
:http3 true
:http3-cert-path "cert.pem"
:http3-key-path "key.pem"})
Expect: 100-continue and zero-copy file bodies.:http2c).Alt-Svc, with
certificate reloading.StreamableResponseBody, and a streaming body for SSE and long-poll.Conformance: h2spec 146/146 over TLS, Autobahn TestSuite 517/517, h3spec 75/77 (the two failures are checks inside libquiche).
On an M1 Pro laptop (8 CPUs, JDK 25), a 13-byte response, server and load generator sharing the cores:
| req/s | allocated per request | |
|---|---|---|
| HTTP/1.1 GET | 124k | 393 B |
| HTTP/1.1 pipelined | 1.4M | 235 B |
| HTTP/2 GET over TLS | 745k | 1.1 KB |
| HTTP/3 GET | 73k | 801 B |
| WebSocket echo | 1.0M msg/s | 333 B |
In a separate-process comparison with http-kit, Jetty, Aleph and Netty, enso has the highest throughput on every scenario above and allocates 393 bytes per HTTP/1.1 request where the others allocate 3.6 to 4 KB. doc/performance.md has latency percentiles, uploads, and the full comparison.
Requirements: JDK 21 or later and Clojure 1.12 or later. HTTP/3 runs on
Linux (glibc 2.28+ or musl) and macOS 11+ on Apple Silicon, and on JDK 24+
needs --enable-native-access=ALL-UNNAMED.
run-server option and its default.The TLS layer (SSLEngine over SocketChannel) follows the pattern used
by Helidon Níma
(Apache 2.0).
Ensō implements it from scratch; no code was copied.
Copyright © 2026 Max Penet.
Distributed under the Mozilla Public License 2.0 (FAQ).
Can you improve this documentation?Edit on GitHub
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |