Skip to content

Express 5.2.1 (Node.js 24 + node-postgres)

Benchmark · Express · July 2026

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

At a glance

VersionExpress 5.2.1 on Node.js 24 — new entrant this round
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 code103
Podiumsnone of 38 combinations — best finish #4, on all three minimal-baseline levels
Sourceexpress-app-v5.2.1

The verdict in one sentence: the most-used Node framework was conspicuously missing in January, and its debut shows why the omission mattered — Express 5 on an equal deployment gives up nothing measurable to Fastify at database-API workloads.

Implementation

Added by popular demand, and deliberately written as a line-for-line sibling of the Fastify app: same node:cluster primary, same per-worker pg pool sized to a ~100-connection aggregate, same six handlers (app.js):

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

    const app = express();
    app.use(express.json());

    app.get('/api/perf-minimal', async (req, res) => {
        const result = await pool.query('SELECT status, ts FROM public.perf_minimal()');
        res.json(result.rows);
    });
    // ... five more handlers ...
    app.listen(3102, '0.0.0.0');
}

103 lines against Fastify's 102. Express 5's native async-handler support means no wrapper utilities, no next(err) boilerplate — the code reads identically to the Fastify version with res.json() in place of a return.

Results

The dead heat with Fastify

This is the page's central table. Across scenarios, Express and Fastify are one ranking slot and a rounding error apart:

CombinationExpressFastifyGap
Minimal, 100 VU16,140 (#4)16,243 (#3)−0.6%
Minimal, 200 VU15,001 (#4)15,214 (#2)−1.4%
Minimal, 500 VU13,235 (#4)13,180 (#5)+0.4%
POST, 50 VU / 10 rec4,097 (#8)4,111 (#6)−0.3%
Params, 50 VU12,418 (#8)12,494 (#7)−0.6%
Large, 25 VU / 100 KB1,390 (#5)1,389 (#6)+0.1%

The sign flips depending on the cell — at 500 VU on the minimal baseline Express is ahead. The largest gap anywhere in the 38 combinations is the 1 VU perf-test path: 611 vs 752 req/s, 19% behind Fastify. That is the one combination where per-request framework overhead is paid sequentially instead of being hidden behind concurrent database waits; everywhere else the difference stays within about ±1.5%.

Where the driver capped it

Like Fastify, Express inherits node-postgres's ceiling on body-heavy work: 4,097 req/s on POST at 50 VU / 10 records against 7,461 for Bun and 7,238 for Deno running postgres.js — the same JSON body through a different driver pipeline. On perf-test it holds #13 at 100 VU / 1 record (2,578 req/s), five req/s behind Fastify's #12.

Latency

p99 of 23 ms on the minimal baseline at 100 VU, 14 ms on params at 50 VU, and 11 of 16 perf-test combinations under 1 s p99 — the field-standard score. One honest blemish: at the heaviest combination (200 VU / 500 records) Express posted the fattest tail in the field, 6,944 ms p99, despite a median (1,495 ms) that was third-best in that cell. The middle of its distribution is excellent under crush load; the last percentile is not.

Resource usage

Peak memoryAvg memoryAvg CPU
1,094 MB577 MB109%

Second-highest peak in the field, 83 MB under Fastify's 1,177 MB — eight V8 processes cost about a gigabyte regardless of which router runs inside them. The quartet's postgres.js pair did the same job in 340 MB (Bun) and 740 MB (Deno).

Analysis

Express's debut is the cleanest demonstration of the quartet finding: at DB-API workloads, the framework layer above the driver is noise. Four near-identical apps — Fastify, Express, Bun, Deno — converged within ~2% on the minimal baseline (16,243 / 16,140 / 16,106 / 16,436 at 100 VU). What actually separated them was the driver (node-postgres vs postgres.js, worth ~80% on POST throughput) and the memory model (340 MB to 1,177 MB peak for the same 8-process layout). Express's middleware chain, the historic performance scapegoat, cost roughly one percent against Fastify — measurable only if you squint, and inverted in several cells.

The practical reading for the largest framework community in the Node ecosystem: if your API is a thin layer over PostgreSQL, there is no throughput case for migrating off Express 5. There is, however, a case for caring about the driver underneath it and about whether you can afford a gigabyte of peak RSS for a clustered deployment.

January → July movement: none to report — Express was not in the January round, which is precisely why it was added. Note that this round's numbers are not comparable to January's for any framework: the fairness overhaul (one worker per core, equalized pools) changed absolute figures across the board, so only rankings carry over.

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: Bun →

Comments