Cross-posted from my blog. The original, with any updates, lives on fabwaseem.com.

Node.js 26 became the Active LTS line on October 28, 2026 with v26.13.0 "Lithium", and Node 24 moved to Maintenance LTS on October 20. If you're deciding between Node 24 vs Node 26 for a production app, this post covers what changes, what breaks, and how the two compare on a few benchmarks I ran on the same machine tonight. The short version: Node 26 was faster at JSON serialization, async-heavy code and a plain node:http server, but slower in two places you might not expect, fetch() and inserting a million keys into a Map.

Node 24 vs Node 26 at a glance

Node 24 "Krypton" Node 26 "Lithium"
Version tested v24.22.2 v26.13.0
Status (Nov 2026) Maintenance LTS since Oct 20, 2026 Active LTS since Oct 28, 2026
End of life April 30, 2028 April 30, 2029
V8 13.6 14.6
Undici (powers fetch) 7.30.1 8.12.2
NODE_MODULE_VERSION 137 147
Bundled npm 11.19.1 11.20.0
Temporal global not available on by default

Dates come from the Node.js release schedule. Versions are what process.versions printed on each binary.

What's new in Node 26

From the Node 26.0.0 release notes and checked on v26.13.0:

  • Temporal is enabled by default. Temporal.Now.plainDateISO('Asia/Karachi') works with no flag. On Node 24, Temporal is undefined.
  • V8 14.6 brings Map.prototype.getOrInsert() / getOrInsertComputed() (the upsert proposal) and Iterator.concat().
  • Undici 8, so the global fetch() is a different major version of the HTTP client.
  • TypeScript type stripping still works out of the box for .ts files, as it does on Node 24. --experimental-transform-types was removed, so enums and namespaces that need transformation won't run without a build step.
// Node 26 only const counts = new Map(); for (const word of ['a', 'b', 'a']) { counts.set(word, counts.getOrInsert(word, 0) + 1); } const today = Temporal.Now.plainDateISO('Asia/Karachi'); console.log(today.add({ days: 30 }).toString()); const all = Iterator.concat([1, 2].values(), [3].values()).toArray(); // [1, 2, 3] 

Breaking changes to check before upgrading

These are the ones most likely to hit a typical Node.js, NestJS or Next.js codebase:

  1. Native addons must be rebuilt. NODE_MODULE_VERSION went from 137 to 147. Anything with a compiled .node file (bcrypt, sharp, better-sqlite3, canvas) needs a fresh install on Node 26. Delete node_modules in your Docker build rather than copying it from a Node 24 stage.
  2. http.ServerResponse.prototype.writeHeader() is gone. It was a legacy alias. On v26.13.0 typeof res.writeHeader is undefined. Use writeHead().
  3. The _stream_* legacy modules are removed (_stream_readable, _stream_writable and friends). Old dependencies that require('_stream_readable') will crash at import.
  4. module.register() is runtime-deprecated. Running a loader that calls it prints DEP0205 DeprecationWarning: module.register() is deprecated. Use module.registerHooks() instead. It still works, but plan to move custom loaders to registerHooks().
  5. --experimental-transform-types is removed. If you run .ts with enums directly through Node, switch to erasableSyntaxOnly style code or keep a compiler step.

A quick way to find the first two in a codebase:

grep -rn "writeHeader(\|_stream_readable\|_stream_writable\|module.register(" src/ node_modules/.pnpm 2>/dev/null | head 

Node 24 vs Node 26 performance: benchmark setup

I ran these on November 3, 2026 on one Linux VM with 8 vCPUs (Intel Xeon) and 16 GB RAM. The machine was shared with other work (load average around 1.5 before starting), so treat small differences as noise. To limit that:

  • Each benchmark process was pinned to one CPU with taskset.
  • Node 24 and Node 26 runs were interleaved over 5 rounds, and I report the median of the 5 rounds.
  • The HTTP load generator (autocannon, 100 connections, 10 s) always ran on Node 24 on separate CPUs, so only the server changed.
  • The fetch() test sent 20,000 requests with 50 concurrent loops to a fixed Node 24 server, so only the client changed.

The scripts are plain .mjs files: JSON.parse/JSON.stringify on a 20,000-item document, sorting 300,000 numbers, setting 1 million string keys in a Map, a global regex replace, SHA-256 over 16 MB, allocating 2 million small class instances, and 1 million sequential awaits.

Benchmark results

Lower is better for times, higher is better for requests per second. Median of 5 rounds.

Test Node 24.22.2 Node 26.13.0 Change
JSON.parse (20k items) 11.79 ms 10.46 ms 11% faster
JSON.stringify (20k items) 7.20 ms 4.53 ms 37% faster
Sort 300k numbers 54.6 ms 51.7 ms 5% faster
Map.set 1M string keys 396.7 ms 507.5 ms 28% slower
Regex replace 2.06 ms 1.72 ms 16% faster
SHA-256 over 16 MB 9.57 ms 9.17 ms 4% faster (within noise)
2M class instances 47.8 ms 35.0 ms 27% faster
1M sequential await 58.6 ms 35.0 ms 40% faster
node -e 0 startup 22.3 ms 20.7 ms 7% faster
RSS after startup 41 MB 41 MB same
node:http server, req/s 73,079 79,653 9% more
node:http p99 latency 3 ms 2 ms lower
fetch() client, req/s 8,442 7,601 10% fewer

What stood out:

  • JSON.stringify and await got much cheaper. Those two show up everywhere in API servers, so the 9% higher node:http throughput is consistent with them.
  • fetch() was slower in 4 of 5 rounds. Node 26 ships Undici 8. If your service makes lots of outbound HTTP calls, measure your own workload before and after.
  • Map.set with 1 million new string keys was slower in every round. The Node 24 numbers for this test varied a lot (336 to 513 ms), so the size of the gap is uncertain, but the direction was consistent. Code that builds very large maps in a hot path is worth profiling.

These are microbenchmarks on one VM. They tell you where to look, not what your app will do.

How to upgrade from Node 24 to Node 26

# 1. Switch locally nvm install 26 && nvm use 26 # or: fnm use 26 / volta install node@26 # 2. Reinstall so native addons rebuild against ABI 147 rm -rf node_modules && npm ci # 3. Surface deprecations your code triggers NODE_OPTIONS=--trace-deprecation npm test 

Then update the places that pin the version:

# Dockerfile FROM node:26-alpine AS deps 
// package.json { "engines": { "node": ">=26" } } 

Also update .nvmrc, your CI matrix and the Node version in your hosting panel. If you deploy Next.js in Docker, the multi-stage setup in my Next.js Dockerfile guide works the same with node:26-alpine as the base image.

Should you upgrade to Node 26 now?

  • New projects: start on Node 26. It's the Active LTS line and is supported a year longer than Node 24.
  • Existing Node 24 apps: there's no rush. Node 24 gets security fixes until April 30, 2028. Upgrade when you next touch your Docker base image, after rebuilding native addons and running your tests with --trace-deprecation.
  • Services that are mostly outbound HTTP: benchmark your own fetch() traffic first, because that was the one place Node 26 was clearly slower in my test.

If you're also weighing runtimes rather than versions, I compared Bun vs Node on real workloads earlier.

FAQ

Is Node 26 LTS?

Yes. Node 26 entered Active LTS on October 28, 2026 with v26.13.0, codename "Lithium". It stays Active LTS until October 20, 2027, then Maintenance LTS until April 30, 2029.

When does Node 24 reach end of life?

April 30, 2028. Node 24 has been in Maintenance LTS since October 20, 2026, which means security and critical fixes only.

Is Node 26 faster than Node 24?

In my benchmarks on one 8-vCPU VM, Node 26 was faster at JSON.stringify (37%), sequential await (40%) and as a node:http server (9% more requests per second). It was slower for the fetch() client (10% fewer requests per second) and for inserting 1 million keys into a Map (28% slower). Measure your own workload.

What breaks when upgrading from Node 24 to Node 26?

The common ones are native addons that need rebuilding (NODE_MODULE_VERSION 147), the removed res.writeHeader() alias, the removed _stream_* modules, the removed --experimental-transform-types flag, and a runtime deprecation warning for module.register().

Does Node 26 have Temporal?

Yes. The Temporal global is enabled by default in Node 26. In the official Node 24.22.2 binary, typeof Temporal is 'undefined'.

Originally published on fabwaseem.com.