Orisha

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.

The shape of it

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.

Pattern Router

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).

Static Files at Compile Time

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.

One Flow, Every Platform

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.

Dynamic When You Want It

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.

Proven in production

This site runs on it

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.

Measured, honestly

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.

Tiny deployments

Static binaries with no runtime dependencies. FROM scratch Docker images. Edge, lambda, embedded — anywhere binaries run.