Performance benchmarks

These benchmarks help you choose a Vext HTTP adapter. They keep the Vext application fixed and compare the five supported adapters under the same light Normal workload. They are an input to adapter selection—not a substitute for load-testing your application with its real middleware, authentication, logging, database access, and deployment topology.

At a glance

  • This is an adapter comparison, not a cross-framework league table. Each row runs the same Vext routes, Normal bootstrap, handler mode, HTTP contract, middleware fixture, and load protocol; only the adapter changes.
  • Native has the highest throughput in this host and workload. That is a local observation, not a claim that it is universally best.
  • Fastify and Koa are the next fastest adapters in this sample; Hono and Express trade throughput for their own programming and ecosystem choices. Use the detailed CV and latency data before treating small differences as meaningful.
  • Choose for integration and migration needs first, then reproduce with your workload. Native is the dependency-light default. Select Fastify, Express, Koa, or Hono when their ecosystem is the better fit.

Scope: This page compares the cost of the same Vext Normal application through different Vext adapters. The Fastify, Hono, Express, and Koa columns are not standalone/raw-framework results and do not represent performance under each framework's recommended production configuration. Make production decisions from benchmarks of your application, real middleware, and deployment configuration.

Current results

This formal run was recorded at 2026-08-15T00:07:37.413Z from clean Vext source main@772d3eab9f3826a55526deaf2ad6b1c128bda446 (Vext 1.0.1; Node.js v20.20.2). Every value is the median requests per second from 7 rounds; higher is better for that scenario.

ScenarioNativeHonoFastifyExpressKoa
JSON response25,085.8211,158.1922,191.287,651.8219,017.46
Route parameters24,773.110,65221,961.467,554.3718,678.55
Handler business chain21,802.919,38718,865.67,155.216,527.64
Route middleware chain21,584.739,38318,729.17,137.6416,219.64

All 20 adapter/scenario measurements completed with zero errors, timeouts, and non-2xx responses. Per-scenario CV ranged from 0.2%–1.4%. The full per-round sample, P50/P99, exact versions, provenance, and route-lifecycle telemetry appear below on this page.

Why this comparison

The user-facing choice is which Vext adapter to use, so every target runs the same Vext Normal application. The routes, defineRoutes() loading, route matching, request/response objects, middleware fixture, handler mode, response contract, process priority, and Autocannon protocol are fixed. Only the adapter changes.

The fixture deliberately turns off optional request features that these GET scenarios do not use: access logging, generated request IDs, CORS, rate limiting, response wrapping, body parsing, request context, session, CSRF, security headers, frontend rendering, and application logging. It retains the Normal bootstrap and route lifecycle. This makes the comparison focused and repeatable; it is not an all-features production or database/I/O benchmark.

Why not publish “production-stack” or “bare-path” rankings?

Production load tests are essential before release, but authentication, logging, security, middleware, data and external I/O, deployment topology, hardware, and business complexity all vary. Put those results in one cross-framework RPS table and you measure the full application stack; you cannot reliably attribute the result to the framework or adapter.

At the other extreme, bare paths or the shortest HTTP path are useful maintainer diagnostics, but they omit the Normal bootstrap, route lifecycle, request/response adaptation, and middleware integration that Vext users actually select. They should not rank user-facing adapter choices.

This page fixes the same Vext Normal application and load protocol, then changes only the adapter. It measures the Vext adapter integration-path cost under a fixed, reproducible workload, not the independent performance of Fastify, Hono, Express, or Koa. Production decisions should still use load tests of your real application.

Choosing an adapter

NeedSuggested starting pointCheck before committing
A new project with fewer HTTP framework dependenciesNative (default)Measure the real workload against your latency and throughput targets
A requirement for Fastify-related capabilitiesFastifyVext middleware and native framework middleware have different signatures; verify the integration boundary
An Express or Koa migration and existing team expertiseMatching adapterValidate how existing middleware will be adapted instead of choosing by overhead percentage alone
Hono or Web Standards style in a Node.js serviceHonoThis is a Node.js adapter, not an Edge-runtime guarantee; measure any bridge-sensitive workload

See the Adapter guide for installation and configuration details.

Methodology

ItemCurrent formal sample
EnvironmentNode.js 20.20.2, Windows x64, Intel i7-9700, 32 GiB RAM
Load50 connections, pipelining 10, 10 seconds per measurement
Stability5-second warmup, median of 7 rounds, rotating round order, CV ≤ 20%
ProcessesThe runner and measured child processes use the same normal priority, 0
DependenciesFastify 5.12.0, Hono 4.13.2, @hono/node-server 2.1.1, Express 5.2.1, Koa 3.2.1, @koa/router 15.7.0, Autocannon 8.0.0

Before a formal run, the runner checks these dependencies against npm latest for that date. It refuses citable output when versions or source identity drift, or when any response is non-2xx, a connection fails or times out, a result is missing, or the CV gate fails. Targets are interleaved by round to reduce time drift that would otherwise consistently favor one implementation.

Full formal sample

This complete formal sample is generated from the same artifact as the current-result summary above. It remains on this page so the conclusion, method, and every measurement can be reviewed together.

Run identity

FieldValue
Recorded at (UTC)2026-08-15T00:07:37.413Z
Source revisionmain@772d3eab9f3826a55526deaf2ad6b1c128bda446
Source stateclean (required for formal publication)
Vext1.0.1
Node.jsv20.20.2
Protocol10s × 7 rounds; 50 connections; pipelining 10; 5s warmup; sync handler; CV ≤ 20%

Scenarios

PathScenarioWhat it exercises
/jsonJSON responseRoute matching and JSON serialization.
/users/42Route parametersDynamic route matching and parameter extraction.
/chainHandler business chainThree layers of handler business logic and a JSON response.
/middleware-chainRoute middleware chainThree route-level middleware layers and a JSON response.

Every measured sample

ScenarioAdapterRPS samples (every round)MedianP50P99Errors / timeouts / non-2xxCV
JSON responseNative25,688, 25,085.82, 25,208, 25,256, 24,720, 24,908.37, 24,882.1925,085.8219 ms25 ms0 / 0 / 01.2%
JSON responseHono11,269.46, 11,145.6, 11,156, 11,209.1, 11,214.4, 10,998.4, 11,158.1911,158.1943 ms71 ms0 / 0 / 00.7%
JSON responseFastify22,609.6, 22,004.8, 22,227.64, 22,191.28, 21,988.8, 22,170.91, 22,329.622,191.2822 ms27 ms0 / 0 / 00.9%
JSON responseExpress7,668.8, 7,657.64, 7,635.6, 7,651.82, 7,677.64, 7,610.37, 7,636.197,651.8264 ms78 ms0 / 0 / 00.3%
JSON responseKoa19,080, 19,008.73, 19,257.46, 18,901.1, 19,017.46, 18,864, 19,206.5519,017.4625 ms32 ms0 / 0 / 00.7%
Route parametersNative24,690.19, 24,688, 24,938.91, 25,001.46, 24,773.1, 24,784.73, 24,419.6424,773.119 ms26 ms0 / 0 / 00.7%
Route parametersHono10,735.64, 10,555.28, 10,652, 10,564.73, 10,725.46, 10,541.46, 10,668.7310,65246 ms77 ms0 / 0 / 00.7%
Route parametersFastify21,961.46, 21,808, 21,654.4, 22,191.28, 22,123.2, 22,031.28, 21,868.821,961.4622 ms28 ms0 / 0 / 00.8%
Route parametersExpress7,572.8, 7,572.91, 7,518, 7,554.37, 7,507.82, 7,567.46, 7,553.287,554.3765 ms86 ms0 / 0 / 00.3%
Route parametersKoa18,960.41, 18,535.64, 18,687.28, 18,348, 18,707.64, 18,625.2, 18,678.5518,678.5525 ms31 ms0 / 0 / 00.9%
Handler business chainNative21,933.82, 22,182.4, 22,205.82, 21,493.1, 21,670.55, 21,802.91, 21,582.421,802.9122 ms28 ms0 / 0 / 01.2%
Handler business chainHono9,404.21, 9,437, 9,313.8, 9,495.4, 9,276.21, 9,331.46, 9,3879,38752 ms88 ms0 / 0 / 00.8%
Handler business chainFastify18,973.82, 18,865.6, 19,245.82, 18,819.2, 19,152, 18,590, 18,853.218,865.625 ms31 ms0 / 0 / 01.1%
Handler business chainExpress7,130.73, 7,159.1, 7,150.8, 7,152.4, 7,194.4, 7,155.2, 7,164.47,155.269 ms91 ms0 / 0 / 00.2%
Handler business chainKoa16,711.6, 16,630.8, 16,662.8, 16,527.64, 16,469.6, 16,524, 16,351.6416,527.6429 ms38 ms0 / 0 / 00.7%
Route middleware chainNative21,670.55, 21,548.37, 21,654.4, 21,584.73, 21,545.46, 21,513.6, 21,957.121,584.7322 ms28 ms0 / 0 / 00.6%
Route middleware chainHono9,401.4, 9,203.4, 9,389.64, 9,204.21, 9,397.4, 9,224.21, 9,3839,38351 ms88 ms0 / 0 / 01.0%
Route middleware chainFastify18,635.28, 18,576.41, 18,729.1, 18,825.46, 18,776, 18,462.91, 18,806.5518,729.125 ms32 ms0 / 0 / 00.7%
Route middleware chainExpress7,418.4, 7,117.64, 7,137.64, 7,159.46, 7,114, 7,156.4, 7,1267,137.6469 ms90 ms0 / 0 / 01.4%
Route middleware chainKoa16,374.91, 16,171.28, 16,281.1, 16,132, 16,358.19, 16,219.64, 16,08016,219.6429 ms40 ms0 / 0 / 00.6%

Normal route-lifecycle telemetry

ScenarioAdapterGlobal middlewareRoute registration chainStatus
JSON responseNative12asserted
JSON responseHono12asserted
JSON responseFastify12asserted
JSON responseExpress12asserted
JSON responseKoa12asserted
Route parametersNative12asserted
Route parametersHono12asserted
Route parametersFastify12asserted
Route parametersExpress12asserted
Route parametersKoa12asserted
Handler business chainNative12asserted
Handler business chainHono12asserted
Handler business chainFastify12asserted
Handler business chainExpress12asserted
Handler business chainKoa12asserted
Route middleware chainNative15asserted
Route middleware chainHono15asserted
Route middleware chainFastify15asserted
Route middleware chainExpress15asserted
Route middleware chainKoa15asserted

Exact environment and versions

ItemExact value
Platformwin32 x64
CPUIntel(R) Core(TM) i7-9700 CPU @ 3.00GHz
Memory32 GiB
Process priority0
Vext1.0.1
Hono4.13.2
@hono/node-server2.1.1
Fastify5.12.0
Express5.2.1
Koa3.2.1
@koa/router15.7.0
Autocannon8.0.0
npm latest verification2026-08-14T23:36:04.874Z (https://registry.npmjs.org)

Reproduce the results

Install the lockfile and confirm that the benchmark dependencies still match npm latest:

npm ci
npm run verify:benchmark-deps

Run the public adapter comparison with the same protocol used on this page:

node --expose-gc --max-old-space-size=512 test/benchmark/run-adapter-matrix.mjs --formal --scenario all --duration 10 --connections 50 --pipelining 10 --warmup 5 --rounds 7 --max-cv 20 --process-priority 0 --handler-mode sync

This sample uses synchronous handlers. If your platform or permissions require a different priority, choose an available value and treat the result as a new environment baseline rather than comparing absolute numbers with this page.

The runner uses the local Autocannon programmatic API and starts and stops its targets automatically. This page includes every sample, P50/P99, exact versions, provenance, and route-lifecycle telemetry. See the benchmark README for all runner options and artifact merge rules.

Test your application

A framework microbenchmark answers only “what does the core HTTP path cost?” Before production, run a workload that includes at least:

  1. your authentication, logging, response wrapping, and middleware;
  2. real or controlled substitutes for databases, caches, and external APIs;
  3. warmup, multiple rounds, throughput, P95/P99 latency, error rate, and resource use;
  4. the production Node.js version, process count, container limits, and reverse proxy.

Limitations

  • The current results come from one Windows host; they do not represent Linux, containers, or cloud platforms.
  • These are small HTTP microbenchmarks. They do not measure developer experience, plugin quality, maintainability, or complete business latency.
  • Do not combine absolute values from different dates, machines, dependency versions, handler modes, or load protocols into one ranking.
  • The table compares Vext adapters only. Raw and shortest-path diagnostics are maintained separately and are not user-facing adapter rankings.