Skip to content

Fastify 5.10.0 (Node.js 24 + node-postgres) ​

Benchmark · Fastify · July 2026

Part of the PostgreSQL REST API Benchmark, July 2026 series.

At a glance ​

VersionFastify 5.10.0 on Node.js 24
PostgreSQL drivernode-postgres (pg) 8.22.0 — 12 connections per worker, ~96 aggregate
Concurrency modelnode:cluster, one worker per core (os.availableParallelism()) — 8 processes
Lines of code102 (the fewest of any hand-written app in the field)
Podiums🥈 1 · 🥉 1 — of 38 combinations
Sourcefastify-app-v5.10.0

The verdict in one sentence: Fastify is the best of the Node pair by a hair, podiums on the minimal baseline — and everything else about its result sheet is really a report about the pg driver and the cost of clustering V8.

Implementation ​

This round's fairness overhaul is visible in the first ten lines of app.js: the single-threaded event loop is multiplied by node:cluster so it can use the whole machine, like the natively multi-threaded runtimes always could. Each worker gets its own pg pool, sized so the aggregate stays at roughly 100 connections:

js
js
const WORKERS = parseInt(process.env.WORKERS || '') || os.availableParallelism();

if (cluster.isPrimary) {
    for (let i = 0; i < WORKERS; i++) {
        cluster.fork();
    }
    cluster.on('exit', () => cluster.fork());
} else {
    // Pool is per cluster worker; workers x max ~= 100 aggregate
    const pool = new Pool({ /* ... */ max: Math.max(2, Math.floor(100 / WORKERS)) });

    const fastify = Fastify({ logger: false });
    fastify.get('/api/perf-minimal', async (request, reply) => {
        const result = await pool.query('SELECT status, ts FROM public.perf_minimal()');
        return result.rows;
    });
    // ... five more handlers ...
    fastify.listen({ port: 3101, host: '0.0.0.0' });
}

Six endpoints in 102 lines — async handlers returning result.rows directly, with Fastify's serializer doing the rest. Nothing else was tuned.

Results ​

Where it podiumed ​

The minimal baseline is Fastify's scenario. At 200 VU only Go was faster:

Minimal baseline100 VU200 VU500 VU
req/s16,243 (#3)15,214 (#2)13,180 (#5)

And this is where the quartet story starts. Fastify, Express, Bun and Deno ran near-identical application code this round, and on the minimal baseline at 100 VU they landed within about 2% of each other: Fastify 16,243, Express 16,140, Bun 16,106, Deno 16,436. The runtime and the framework mattered far less than January's single-process deployments suggested.

Where the driver set the ceiling ​

Once the request carries a JSON body or twenty typed parameters, Fastify's numbers stop tracking Bun/Deno — not because of the framework, but because Fastify rides node-postgres while Bun and Deno ride postgres.js:

CombinationFastify (pg)Bun (postgres.js)Deno (postgres.js)
POST, 50 VU / 10 rec4,111 (#6)7,461 (#2)7,238 (#3)
Params, 50 VU12,494 (#7)15,156 (#2)14,797 (#3)
perf-test, 50 VU / 1 rec2,644 (#12)3,068 (#4)3,065 (#5)

Same JSON body, same PostgreSQL function, roughly 81% more throughput on POST for the postgres.js pair. On the comprehensive perf-test scenario Fastify sits mid-field throughout — 2,583 (#12) at 100 VU / 1 record, 1,384 (#18) at 200 VU / 10 records.

Latency ​

Clean where it is fast: p99 of 3 ms at 1 VU on perf-test, 22 ms on the minimal baseline at 100 VU, 13 ms on params at 50 VU. Fastify held p99 under 1 s in 11 of 16 perf-test combinations — the field's standard score (only Bun and Swoole managed 12). Its heaviest-load tail is comparatively tidy: 4,156 ms p99 at 200 VU / 500 records, against Express's 6,944 ms in the same cell.

Resource usage ​

Peak memoryAvg memoryAvg CPU
1,177 MB600 MB92%

The highest peak memory of all 20 services — the direct cost of running 8 V8 processes, each with its own heap, JIT state, and pool. Bun's 8-process deployment peaked at 340 MB, Deno's at 740 MB, Express's at 1,094 MB. Throughput-per-megabyte is where Fastify's result sheet looks worst: Go delivered more requests from 59 MB peak.

Analysis ​

The headline finding is negative, and it is the most useful one on this page: the "Fastify is much faster than Express" folk wisdom did not survive contact with equal deployment. At 200 VU on the minimal baseline the gap is 15,214 vs 15,001 — Express is 1.4% behind, within run-to-run noise. The only combination with a visible Fastify edge is the 1 VU sequential path (752 vs 611 req/s on perf-test), where per-request framework overhead is not amortized; under concurrency it evaporates. When both frameworks spend their time waiting on the same driver and the same PostgreSQL function, the router benchmark deltas that separate them in synthetic hello-world tests are simply not reachable.

Within the quartet, Fastify's differentiators are therefore not speed: it shares the Node ecosystem and the pg driver's POST/params ceiling with Express, and it pays the largest memory bill of the four. What it delivers is the shortest implementation in the entire benchmark — 102 lines for six endpoints — and a podium spot on the baseline.

January → July movement: rankings only — January ran Fastify as a single process, so absolute numbers describe a different deployment and are not comparable. With one worker per core, Fastify ranks #2–#3 on the minimal baseline and mid-field wherever the driver dominates; the January picture of event-loop frameworks trailing the compiled field was largely a deployment artifact, not a framework property.

Explore on GitHub ​

Everything this page claims can be checked against the running code and the raw output:


Series: Introduction · Overall Analysis · Raw Results

Next framework: Express →

Comments