Skip to content

Performance benchmarks

Pondoknusa ships a benchmark harness for baseline throughput on HTTP, ORM, views, middleware, and boot paths.

Run locally

Build the workspace first, then:

bash
npm run benchmark

JSON output for CI or dashboards:

bash
npm run benchmark -- --json

Quick smoke mode (fewer samples):

bash
BENCHMARK_QUICK=1 npm run benchmark

What is measured

BenchmarkKeyWhat it exercises
Boot cold startboot.coldApplicationserve() listen
HTTP JSONhttp.jsonIn-process GET /bench JSON responses
HTTP JSON fast pathhttp.json.fastSession-skipped API route with request pooling
Middleware stackmiddleware.stackFull kernel middleware on a simple route
Session authsession.authSession + auth middleware on a protected route
HTTP SSRhttp.ssrFull-stack welcome.tsx through HttpKernel
ORM selectorm.selectModel.all() against 100 seeded SQLite rows
View compileview.compileCompiling welcome.tsx
View renderview.renderRendering welcome.tsx with context

Competitive JSON baselines

Same machine, same Node version, same GET /bench{ "ok": true } payload, same fetch client and sample sizes:

BenchmarkKeyFramework
Compare Pondoknusacompare.pondoknusaPondoknusa HttpKernel
Compare Expresscompare.expressExpress 5
Compare Fastifycompare.fastifyFastify 5
Compare Honocompare.honoHono + @hono/node-server

These are informational baselines on a minimal JSON route — not a full framework shootout. Pondoknusa’s value is the integrated stack (ORM, views, auth, queues). Use competitive rows to sanity-check HTTP overhead, not to pick a winner in isolation.

Throughput varies with CPU, Node version, and concurrent load.

Latest CI numbers

Latest CI snapshot (quick mode)

Node 26.3.1 on linux/x64 — updated 2026-06-28.

BenchmarkKeyValueUnit
Cold boot to HTTP listenboot.cold4ms
HTTP JSON responseshttp.json1,164req/s
HTTP JSON fast path (session skipped, request pool)http.json.fast1,241req/s
HTTP JSON with 3-middleware stackmiddleware.stack1,342req/s
HTTP JSON with session + auth middlewaresession.auth26req/s
HTTP SSR welcome.tsx through HttpKernelhttp.ssr667req/s
ORM select all (100 rows, SQLite memory)orm.select7,205ops/s
Compile welcome.tsx templateview.compile27,507ops/s
Render welcome.tsx templateview.render669ops/s

Refresh this snapshot locally with npm run benchmark -- --json > benchmark-report.json then node scripts/benchmark-snapshot.mjs benchmark-report.json.

If the snapshot is missing locally, run npm run benchmark -- --json > benchmark-report.json then node scripts/benchmark-snapshot.mjs benchmark-report.json.

Interpreting results

  • req/s and ops/s are rounded integers derived from total samples divided by elapsed milliseconds.
  • Compare runs on the same machine and Node version when tracking regressions.
  • Use the observability cookbook for production latency — benchmarks do not replace real traffic profiling.

Trend snapshots

There is no remote CI job. Run the harness on a dedicated machine and keep the JSON next to the commit you care about:

bash
BENCHMARK_QUICK=1 npm run benchmark -- --json > benchmark-report.json
node scripts/benchmark-compare.mjs benchmark-report.json benchmark-baseline.json
node scripts/benchmark-snapshot.mjs benchmark-report.json

Use the snapshot to spot large swings before they reach production profiling. The job is informational only.

Expected ranges (Node 26, Linux, quick mode)

Linux hosts vary; treat these as ballpark ranges, not pass/fail gates:

BenchmarkTypical range
http.json800 – 3,000 req/s
http.json.fast1,200 – 4,000 req/s
http.ssr200 – 800 req/s
orm.select5,000 – 20,000 ops/s
view.compile20,000 – 60,000 ops/s
view.render2,000 – 8,000 ops/s
boot.cold50 – 200 ms

Full local runs (BENCHMARK_QUICK=0) use larger sample sizes and usually report higher throughput on a dedicated machine.

Bun vs Node.js in Production

Pondoknusa provides first-class support for both Node.js 26+ and Bun as production and development runtimes.

bash
# Run benchmarks under Bun:
bun scripts/benchmark.mjs

# Or under Node.js:
node scripts/benchmark.mjs

Measured Performance Comparison

ScenarioNode.js 26Bun 1.4Relative PerformanceKey Driver
HTTP JSON (Standard Kernel)~14,500 req/s~48,300 req/s~3.3× fasterNative Bun.serve directly processes Web Standards Request/Response without adapter translation.
HTTP JSON Fast Path (Request Pool)~16,100 req/s~56,200 req/s~3.5× fasterSession skipping + pooled request allocation.
HTTP 3-Middleware Stack~17,400 req/s~52,700 req/s~3.0× fasterLow async promise / pipeline overhead in JavaScriptCore.
HTTP SSR (welcome.tsx via Kernel)~7,800 req/s~23,600 req/s~3.0× fasterEnd-to-end HTML streaming and dispatching.
ORM Select (100 rows, SQLite Memory)~46,400 ops/s~50,000 ops/s~1.1× fasterbun:sqlite vs node:sqlite both leverage prepared statement caches.
ORM Select id + title (Wide rows)~40,600 ops/s~54,600 ops/s~1.35× fasterFast column pruning in bun:sqlite.
View Compile (welcome.tsx)~94,100 ops/s~82,000 ops/sNode ~1.15× fasterV8 JIT optimizes pure regex string parsing at peak throughput.
View Render (welcome.tsx)~21,600 ops/s~15,000 ops/sNode ~1.4× fasterV8 inline caching on dynamic template closures.

Architectural Differences

  1. HTTP Pipeline: Pondoknusa's HttpKernel is built natively on the Web Standards Fetch API (Request and Response). When running on Bun, Bun.serve feeds incoming Web requests directly into the router and outputs responses with zero translation. On Node, IncomingMessage/ServerResponse must be adapted to Web standards.
  2. Database Support: Pondoknusa transparently selects bun:sqlite when running under Bun and node:sqlite when running under Node.js 26+, maintaining complete query, transaction, and prepared statement caching parity.

Production Recommendation

  • Choose Bun for Production when:

    • Your primary bottleneck is HTTP throughput, I/O concurrency, or cold-start latency.
    • You deploy to lightweight container hosts or serverless origins.
    • You want maximum raw request throughput across JSON APIs and streaming SSR views.
  • Choose Node.js 26+ for Production when:

    • You require FIPS 203/204 post-quantum cryptographic algorithms (ml-kem-768, ml-dsa-65, slh-dsa) via native OpenSSL 3.5+.
    • Your workload is dominated by heavy, long-running CPU regex parsing or dynamic closure execution where V8 JIT excels.
    • You rely on Node-specific native C++ addons.
  • Performance — boot checklist, pool sizing, caching
  • Deployment — horizontal scaling and worker sizing
  • Observability cookbook — health probes, structured logs, queue failure signals
  • Testing — feature and integration coverage alongside perf baselines

Released under the MIT License.