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.3785 ms) ✔ reading file 10 , 000 times with callback blocking ( 711.3979 ms) ✔ reading file 10 , 000 times with async parallel ( 512.4789 ms) ✔ reading file 10 , 000 times with async blocking ( 1080.5988 ms) ✔ reading file 10 , 000 times with promise parallel ( 474.045 ms) ✔ reading file 10 , 000 times with promises blocking ( 755.0493 ms) without node:test (node v21.4.0): reading file 10 , 000 times with callback parallel: 402.4896 ms reading file 10 , 000 times with callback blocking: 755.3545 ms reading file 10 , 000 times with async parallel: 413.0469 ms reading file 10 , 000 times with async blocking: 825.5176 ms reading file 10 , 000 times with promise parallel: 408.7469 ms reading file 10 , 000 times with promises blocking: 775.5422 ms without node:test (bun 1.0.26): reading file 10 , 000 times with callback parallel: 580.7146 ms reading file 10 , 000 times with callback blocking: 437.1434 ms reading file 10 , 000 times with async parallel: 589.4524 ms reading file 10 , 000 times with async blocking: 397.4406 ms reading file 10 , 000 times with promise parallel: 584.5042 ms reading file 10 , 000 times with promises blocking: 415.0018 ms 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) });