Compile-time HTTP server for Koru.
Orisha is an HTTP server and pattern-matching router written in Koru and compiled to native
code via Zig. Routes are declared with a concise DSL and compiled down to straight-line
dispatch — the router is gone before the first request arrives. Static files are embedded at
compile time with pre-rendered responses, and serve is a Koru flow over a platform
pump, so the same handler runs on epoll, io_uring, a unikernel with no operating system, or a
wasm reactor.
orisha:static(name: "site", root: "public", fallback: "index.html")
orisha:handler = orisha:router(req)
! [GET /api/health] -> { status: 200, body: "ok", content_type: "text/plain" }
! [*] |> orisha:static-router(name: "site")
orisha:serve(port: 3000)
| shutdown s |> std/io:print.ln(s)
| failed f |> std/io:print.ln(f) Dynamic API routes, static files as the catch-all, one handler — adapted from the mixed-server example in the Orisha repo.
orisha:router matches [GET /users/:id] branches with
parameter extraction and a [*] catch-all. It is a
compile-time transform: pattern branches become dispatch logic, with no runtime overhead
per request. Dispatch is compiled, so it is also profile-guided: Orisha reads orisha.profile (nginx combined
log) at compile time and reorders branches so hot paths compare first — ~15× in the pgo-router-case dispatch microbench
(38.7 → 2.6 ns/op; dispatch only, deliberately favorable demo).
orisha:static embeds a
directory into the binary; responses are pre-rendered with ETags and Cache-Control
headers. static-router serves them
as a whole handler or a router catch-all, with SPA fallback support.
serve is a Koru flow over orisha/pump — epoll and
io_uring on Linux, a unikernel target, and a wasm reactor. Adding a platform is a new
pump body, not a new server. TLS ports included. Runtime file reads go through orisha/io, which keeps missing,
unreadable, and ready files as three distinct answers.
The handler is yours. The full-server example composes
compiled routes, static files, and a live interpreter in one handler: clients POST Koru
source to /eval and it is
evaluated through std/runtime's
budgeted, scoped interpreter. Budgets and scopes live in the standard library — Orisha
does the routing.
korulang.org compiles into a single WebAssembly module and answers HTTP with no socket at all — bytes in, a complete response out. It has also shipped as a native binary, and as a Unikraft unikernel: a 559 KB image serving HTTP in 6 MB of RAM with no operating system underneath.
Against nginx on the same box, Orisha serves static files ~51% faster with 4 workers. On HttpArena's external spec it competes as a board entry — with the discipline that validate plus glob-concurrent-cannon on Linux is ground truth and local wrk is smoke only.
Static binaries with no runtime dependencies. FROM scratch Docker images. Edge, lambda, embedded — anywhere binaries run.
Server, router, pump, and io — generated from the Orisha source
hello, mixed-server, full-server, tls-server, unikernel — on GitHub
Routing in 10 lines, compiled to a kqueue loop with 4 workers
Orisha inside a Unikraft unikernel — 559 KB image, 6 MB of RAM, no Linux
The honest benchmark, with all the caveats
Compilation as configuration, measured against an external spec