← Back to Good Intentions

Benchmarking NTNT 0.5.5

We reran the NTNT benchmark suite against the 0.5.5 release: nine frameworks, seven workloads, and a two-minute memory test. We also ran 0.4.2 and 0.5.5 side by side, under identical conditions, to see how much throughput changed between the two releases.

How the tests ran

Each workload got a 3-second warmup, then three 10-second runs with wrk using four threads and 100 connections. We report the median. Servers and the load generator shared four logical CPUs on a Ryzen 7 host, and PostgreSQL was limited to one CPU and 512 MiB.

The database holds 10,000 seeded rows, and responses are checked against that seed. The template workload runs ten sequential queries before rendering, so it measures a database-backed page, not the template engine alone. The JSON-body workload posts a 74-byte payload.

Throughput depends heavily on available CPU. The homepage chart comes from our March comparison, which ran on a 16-CPU machine, so its numbers are higher for every framework. Compare frameworks within a run rather than across runs.

NTNT 0.5.5 results

WorkloadRequests/secSpread
Plaintext90,7756.6%
JSON response88,4163.7%
Route parameters82,2736.7%
Database, one query21,9622.7%
Database, 20 queries1,7486.8%
Database + template3,3206.2%
JSON body echo74,0805.4%

Spread is the gap between the fastest and slowest run, as a share of the median. Every NTNT workload stayed under 10%, and every sampled response was correct.

0.4.2 and 0.5.5 side by side

To compare the two releases fairly, we ran both official binaries with the same small web application, in identical containers with four HTTP workers. Each version got three 5-second runs after a 2-second warmup, and we alternated which version went first.

Workload0.4.20.5.5Change
Plaintext80,38175,649-5.9%
JSON81,03875,841-6.4%

Throughput was about 6% lower in 0.5.5 on these two workloads. The route-parameter and POST results varied too much from run to run to compare reliably, and this test didn’t cover database work. Download the measurements.

The other eight frameworks

The same run covers Actix Web, Gin, FastAPI, Fastify, Hono on Bun, Django, Express, and Rails. All 63 workload results passed response checks, but ten competitor results varied by more than 10% between runs, and the summary flags them. Worker models also differ: the Node and Bun servers run as a single process, while several others use four workers.

All nine frameworks’ results

Memory over two minutes

In a 120-second JSON-body run, NTNT served 8,524,125 requests (70,989 per second). Memory peaked at 27,879 KiB and grew by 9 KiB during the loaded window. All nine frameworks stayed within the run’s growth limit, which allows the larger of 32 MiB or 20%. Two minutes on one workload can’t rule out a slow leak, but nothing grew here.

Reproduce it

The benchmark repository has the fixtures, launch commands, runtime versions, database seed, response samples, raw wrk output, and memory traces.

Methodology and raw results on GitHub

← NTNT 0.5.5: Workers, Monitoring, and Auth