tech, developers, and the code underneath

issue 035· news·

Node.js 24 and the slow reinvention of the runtime

V8 13.6, npm 11, fetch no longer experimental, and the permission model losing its dashes.

Node.js 24 is out. It becomes LTS in October. The individual items are small; the direction they add up to is not.

what's in it#

V8 13.6. Brings RegExp.escape (finally), Float16Array, Atomics.pause, and explicit resource management — the using declaration:

js
{
  using file = await open("data.txt");
  // ...
}  // file[Symbol.asyncDispose]() called automatically

That last one is a genuinely useful addition to the language. Deterministic cleanup without try/finally pyramids, and it composes with async.

npm 11. Faster, stricter, and with better handling of the lifecycle-script security surface.

AsyncLocalStorage now defaults to AsyncContextFrame, which is a substantially faster implementation. If you use context propagation for request tracing — and if you have an observability stack, you do — this is a real performance improvement you get for free.

The permission model drops the experimental dashes. --permission instead of --experimental-permission.

bash
node --permission --allow-fs-read=./data --allow-net=api.example.com app.js

URLPattern is global. Undici updated, so fetch behavior tracks the platform more closely.

the direction#

Look at what Node has added over the last three major versions: a test runner, a watch mode, .env file support, a permission model, TypeScript type stripping, a SQLite module, and a full fetch stack.

Every one of those was previously a dependency. jest or mocha. nodemon. dotenv. Nothing, because there was no sandbox. ts-node. better-sqlite3. node-fetch or axios.

Node is absorbing its own ecosystem's most common packages into the runtime. This is a direct response to Deno and Bun, both of which shipped batteries-included from day one and made Node's "small core" philosophy look like an excuse.

I think this is correct and overdue. "Small core, rich ecosystem" was a reasonable position in 2012, when the ecosystem was small and trustworthy. In 2025, when a fresh Express app pulls three hundred transitive dependencies and each one is a supply chain risk, every capability moved into the runtime is one fewer package with a postinstall script.

the migration notes#

  • Node 24 requires a newer minimum glibc and macOS version. Check your base images.
  • Some deprecated APIs finally throw instead of warning. Run your test suite before you upgrade, not after.
  • If you are on 20, plan to go to 24 when it hits LTS in October rather than stopping at 22.

the type stripping question#

Node can now run .ts files by erasing types. It does not typecheck. That is the correct division of labor — typechecking belongs in your editor and your CI, not in your production runtime hot path — but it does mean a type error will happily run and fail at runtime.

The workflow that makes sense: tsc --noEmit in CI, node app.ts in production, erasableSyntaxOnly set so you cannot accidentally use syntax that requires a transform.

No build step. That is a real ergonomic win and it has been a long time coming.

Dom, May 6, 2025

get README in your inbox

One dispatch, no noise. Tech and developer news, plus the occasional long piece on the craft.

subscribe →