Looks like node:test side effect. In my tests, promises have almost the same speed. My tests: with node:test (node v21.4.0): ✔ reading file 10,000 times with callback parallel (401.3785ms) ✔ reading file 10,000 times with callback blocking (711.3979ms) ✔ reading file 10,000 times with async parallel (512.4789ms) ✔ reading file 10,000 times with async blocking (1080.5988ms) ✔ reading file 10,000 times with promise parallel (474.045ms) ✔ reading file 10,000 times with promises blocking (755.0493ms) without node:test (node v21.4.0): reading file 10,000 times with callback parallel: 402.4896ms reading file 10,000 times with callback blocking: 755.3545ms reading file 10,000 times with async parallel: 413.0469ms reading file 10,000 times with async blocking: 825.5176ms reading file 10,000 times with promise parallel: 408.7469ms reading file 10,000 times with promises blocking: 775.5422ms without node:test (bun 1.0.26): reading file 10,000 times with callback parallel: 580.7146ms reading file 10,000 times with callback blocking: 437.1434ms reading file 10,000 times with async parallel: 589.4524ms reading file 10,000 times with async blocking: 397.4406ms reading file 10,000 times with promise parallel: 584.5042ms reading file 10,000 times with promises blocking: 415.0018ms My test code: // const test = require('node:test'); const assert = require('node:assert'); const fs = require('node:fs'); const tests = []; const test = async (name, callback) => { tests.push([name, callback]); }; setTimeout(async () => { for await (let item of tests) { const [name, callback] = item; const startTime = performance.now(); let done; const promise = new Promise((resolve) => { done = () => { resolve(); console.log(`${name}: ${(performance.now() - startTime).toFixed(4)}ms`); }; }); const res = callback(null, done); if (res instanceof Promise) { await res; done(); } await promise; } }, 0); test('reading file 10,000 times with callback parallel', (t, done) => { let count = 0; for (let i = 0; i < 10000; i++) { fs.readFile("./text.txt", { encoding: 'utf-8'}, (err, data) => { assert.strictEqual(data, "Hello, world"); count++ if (count === 10000) { done() } }) } }); let read = (i, callback) => { fs.readFile("./text.txt", { encoding: 'utf-8'}, (err, data) => { assert.strictEqual(data, "Hello, world"); i += 1 if (i === 10000) { return callback() } read(i, callback) }) } test('reading file 10,000 times with callback blocking', (t, done) => { read(0, done) }); test('reading file 10,000 times with async parallel', async (t) => { let allFiles = [] for (let i = 0; i < 10000; i++) { allFiles.push(fs.promises.readFile("./text.txt", { encoding: 'utf-8'})) } return await Promise.all(allFiles) .then(allFiles => { return allFiles.forEach((data) => { assert.strictEqual(data, "Hello, world"); }) }) }); test('reading file 10,000 times with async blocking', async (t) => { for (let i = 0; i < 10000; i++) { let data = await fs.promises.readFile("./text.txt", { encoding: 'utf-8'}) assert.strictEqual(data, "Hello, world"); } }); test('reading file 10,000 times with promise parallel', (t, done) => { let allFiles = [] for (let i = 0; i < 10000; i++) { allFiles.push(fs.promises.readFile("./text.txt", { encoding: 'utf-8'})) } Promise.all(allFiles) .then(allFiles => { for (let i = 0; i < 10000; i++) { assert.strictEqual(allFiles[i], "Hello, world"); } done() }) }); let read2 = (i, callback) => { let data = fs.promises.readFile("./text.txt", { encoding: 'utf-8'}) .then(data => { assert.strictEqual(data, "Hello, world") i += 1 if (i === 10000) { return callback() } read(i, callback) }) } test('reading file 10,000 times with promises blocking', (t, done) => { read2(0, done) });