Skip to main content

Benchmarks

Two comparisons, both reproducible from the ligero-examples repository. Absolute numbers depend on your hardware — the point is the shape of the differences, and that you can re-run them yourself.

Framework comparison (same app, four setups)

The same products CRUD app (GET/POST /products, in-memory store) built in each framework and launched identically (installDist → start script, no JVM tuning). From a run on a 4-core machine, JDK 21:

FrameworkStartup (ms)RSS (MB)Throughput (req/s)p50 (ms)p99 (ms)Dist libs (MB)
Ligero (JDK engine)42937113 0492.813.63
Ligero (Jetty engine)59226210 0443.715.15
Spring Boot (MVC / Tomcat)1 9523095 8096.729.220
Javalin (Jetty)62427310 9373.119.58

Startup = median of 4 cold JVM launches (process exec → first HTTP 200). Throughput = GET /products, 50 connections, 8 s, after warmup. RSS = /proc/<pid>/status VmRSS after the load run.

What it says:

  • Ligero's default engine sweeps the board. On the zero-dependency JDK engine (com.sun.net.httpserver) it now leads throughput (~13 k req/s, p50 2.8 ms), starts fastest (~0.43 s, ~4.5× faster than Spring Boot), and ships the smallest dependency tree (3 MB vs 20 MB).
  • This used to read the other way. The JDK engine looked slow (~1 k req/s, p50 44 ms) purely because com.sun.net.httpserver leaves Nagle's algorithm on — which on keep-alive connections adds ~40 ms per response. The engine now disables it (sun.net.httpserver.nodelay) by default; nothing in your app changes. It's a good reminder to profile before blaming the design.
  • The Jetty engine is still one dependency away for teams that want HTTP/2, WebSockets, or Jetty's tuning knobs — the same App.java, only the runtimeOnly server dependency differs.

Verdict — which should you pick?

If you want…PickWhy
Best all-roundLigero (JDK engine)fastest startup, smallest deps, top throughput, plus DI/modules/devtools a micro-framework doesn't ship
HTTP/2 or WebSocketsLigero (Jetty engine)same app, one dependency swap via the ServerEngine SPI
The biggest ecosystem & maturitySpring Bootnot what this benchmark measures — slowest to start (2 s) and heaviest (20 MB), but the ecosystem is unmatched

In one line: Ligero gives you a micro-framework's startup and footprint with top-tier throughput on zero server dependencies — plus DI, modules and devtools built in. Spring Boot remains the pick when the ecosystem outweighs startup, memory and size.

Dependency-injection comparison

Wiring cost of a 100-bean dependency graph (fresh JVMs, median of 5), comparing Ligero's Beans container to reflection/scanning containers:

ContainerMedian wiring timeRelative
Ligero Beans~65 ms (≈ class-loading; the container works in µs)
Guice 7~400 ms~6×
Spring 6.2 (component scanning)~555 ms~8.5×

Explicit lambda bindings do no classpath scanning and no reflective injection, so "wiring" is essentially just running your constructors — which is why it barely registers next to class-loading.

Reproduce

# framework comparison
cd ligero-examples/comparison
./run.sh # writes results.md
RUNS=7 CONC=100 DUR=15 ./run.sh

# both need Ligero published locally first, from the framework repo:
# ./gradlew publishToMavenLocal

The harness (comparison/run.sh + comparison/bench/Load.java, a zero-dependency virtual-thread load driver) builds each app, launches it with identical flags, and records median cold-start, RSS and throughput. It is deliberately simple and honest — one app at a time, warmup before load, medians over cold starts — so you can read exactly how each number is produced.