Skip to content

Begin typing to search this documentation.

Hoplite

Nginx + Hara · one application server

Your application, directly inside Nginx.

Hoplite packages Hara routes, authentication, service management, and deployment into one refined server. Choose a target below and bring a real endpoint online.

Runtime
Nginx + embedded Hara
Artifact
Executable or OCI image
Platforms
macOS and Linux

01 · First application

Choose where it runs.

One endpoint, one published runtime, and no source checkout. Switch targets to get the exact path from install to first response.

app.hal14 lines
(ns app
  (:require [hoplite.core :as h]))

(defn hello [_]
  {:status 200
   :headers {"content-type" "text/plain"
             "x-hoplite" "true"}
   :body "Hello from Hoplite\n"})

(def app
  (h/app
    {:name "hello"
     :resources
     [["/hello" {:get {:handler #'hello}}]]}))

Fastest start

Run the published image.

Install and run
docker run --rm -p 8080:8080 ghcr.io/greenways-ai/hoplite:latest
Verifycurl -i http://127.0.0.1:8080/hello

The image already contains Hoplite and the starter application.

GET/hello
STATUS200 OK
HEADERx-hoplite: true
BODYHello from Hoplite

02 · Equivalent-payload benchmark

Hoplite against raw Nginx.

Both targets use Nginx 1.30.4, the same Debian toolchain, the same 19-byte body, the same response header, and the same load generator. The difference is the embedded Hara application path.

PayloadHello from Hoplite\n
Body19 bytes
Response identitySHA-256 matched
Load4 threads · 128 connections · 20s

Requests / second

Hoplite85,817
Plain Nginx96,307
Hoplite delivers 89.1% of the raw Nginx request rate in this sample.

p50 latency

Hoplite1.36 ms
Plain Nginx1.16 ms
Median request latency under the same thread and connection load.

p99 latency

Hoplite5.30 ms
Plain Nginx5.74 ms
Tail latency from the same three-round wrk sample.

Peak memory under load

Hoplite74.2 MiB
Plain Nginx11.2 MiB
Highest container memory sample observed while each target was loaded.

Hoplite

Runtime executable
44.3 MiB
Deployment image
129.4 MiB
Idle memory
60.7 MiB

Plain Nginx

Runtime executable
4.5 MiB
Deployment image
89.6 MiB
Idle memory
9.4 MiB
All measured rounds
TargetRoundRequests/sp50p99Peak memory
Hoplite185,5231.37 ms5.18 ms66.2 MiB
Hoplite285,8171.36 ms5.58 ms70.5 MiB
Hoplite385,9351.36 ms5.30 ms74.2 MiB
Plain Nginx196,9971.15 ms5.66 ms11.1 MiB
Plain Nginx296,3071.16 ms5.74 ms11.1 MiB
Plain Nginx396,0781.16 ms6.14 ms11.2 MiB
Recorded
Aug 5, 2026, 1:36 AM UTC
Commit
ae994650
Runner
Ubuntu 24.04 GitHub-hosted runner
CPU
INTEL(R) XEON(R) PLATINUM 8573C · 4 logical
Rounds
3 per target
Isolation
Targets run sequentially on one runner

This is a reproducible release sample, not a universal capacity guarantee. The comparison is useful because the payload, Nginx version, build environment and load are held constant.

Reproduce the comparison

Build both targets and record both sides.

The script rejects the run when the response bodies differ, then records every round along with executable size, image size, idle memory and peak memory.

Hoplite vs plain Nginxsame payload · same load
docker build -f docker/Dockerfile.nginx-baseline -t hoplite-nginx-baseline .

bash scripts/benchmark-http.sh \
  ghcr.io/greenways-ai/hoplite:latest \
  hoplite-nginx-baseline \
  benchmark-output/http-benchmark.json

03 · Measured footprint

What each stack occupies.

These are minimal representative deployments returning the same 19-byte response. Java and Python include the same plain Nginx baseline plus their application service; Hoplite and Lua remain one-server deployments.

Hoplite

Deploy image129.4 MiB
Idle memory60.8 MiB
Measured shape
Nginx + embedded Hara
Service surfaces
1 server lifecycle
Hoplite executable
44.27 MiB
What you gain
Routing, auth, management, OpenAPI
What you carry
Young ecosystem; pre-1.0 interfaces

Java

Deploy image377.8 MiB
Idle memory46.2 MiB
Measured shape
Plain Nginx + minimal JVM service
Service surfaces
2 server lifecycles
Application JAR
<0.01 MiB
What you gain
Broad framework and tooling ecosystem
What you carry
Proxy boundary plus JVM runtime envelope

Python

Deploy image205.5 MiB
Idle memory19.1 MiB
Measured shape
Plain Nginx + minimal Python service
Service surfaces
2 server lifecycles
Application source
<0.01 MiB
What you gain
Fast iteration and broad libraries
What you carry
Proxy boundary and worker/process sizing

Lua / Nginx

Deploy image222.7 MiB
Idle memory18.2 MiB
Measured shape
Nginx + Lua module
Service surfaces
1 server lifecycle
Nginx executable
1.20 MiB
What you gain
Lean request-boundary scripting
What you carry
Application conventions assembled separately

Measured on Ubuntu 24.04 GitHub-hosted runner with 4 logical CPUs. Idle memory is the median of 12 samples per component.

Logical Docker image sizes are summed for multi-service stacks; shared registry layers may deduplicate in practice.

The useful claim is not that every Java or Python application has one fixed size. It is that an external proxy and application runtime occupy separate images and separate resident processes, while Hoplite keeps the application inside the Nginx lifecycle.

05 · Documentation

See what happens—and why.

Each section starts with a concrete operation, then explains the runtime or operational reason behind it. Use the example to enter; use the reference to be exact.

Start here · 5 guides

Getting started

Install the published runtime, generate a two-file application, and serve it.

First service
brew install greenways-ai/tap/hoplite
hoplite serve foreground --mode prod .
Why it matters

This is the shortest supported path from an empty machine to a real endpoint. It uses the packaged server rather than asking users to compile Hoplite or assemble a proxy stack.

Open section →
System model · 4 topics

Concepts

See how resources, operations and handler Vars become a worker-local router.

A route is data
["/hello"
 {:get {:name "hello"
        :handler #'hello}}]
Why it matters

The route stores a Var instead of calling the function while configuration is read. Hoplite can validate the resource tree, then resolve and compile the handler once when each Nginx worker starts.

Open section →
Operations · 8 guides

Guides

Build the parts that make an application useful: async work, auth, OpenAPI and production operation.

Yield to Nginx
(defn delayed [_]
  (await (Host/call "nginx" "sleep" [25]))
  {:status 200 :body "resumed"})
Why it matters

When the handler awaits a host capability, the worker can resume other requests. Synchronous handlers stay on the direct path and do not pay for promise state they never use.

Open section →
Interfaces · 8 references

Reference

Look up the exact commands, project keys and public forms used by the current release.

Production contract
hoplite serve check .
hoplite serve build --mode prod .
hoplite serve status .
Why it matters

The reference is where examples become exact contracts. These commands validate the project, build the production plan and inspect the running service without relying on undocumented shell conventions.

Open section →

05 · Current release

Published. Pre-1.0. Built in the open.

Hoplite 0.1.0 ships for Apple Silicon, Intel macOS, ARM64 Linux, and x86-64 Linux, with Homebrew and GHCR distribution. Interfaces remain intentionally pre-1.0 while the bytecode bootstrap and hosting contracts settle.

Release
0.1.0
Distribution
Homebrew · binary · OCI
License
Apache-2.0
Release and roadmap →