Skip to content
chornous.dev

Type two or more letters. Esc closes.

Index of sheets
Theme

Sheet 03 · Writing

All notes

Node.js 26 goes LTS in October, with Temporal switched on

Node.js 26 enables the Temporal API by default, adds Map.getOrInsert and Iterator.concat, and removes a batch of long-deprecated APIs. Test these before it becomes the LTS line next month.

Pl. 97 · pipeline drawing generated from the slug “nodejs-26-temporal-lts”

Node.js 26.0.0 came out on May 5, 2026 as the Current release, and it becomes the LTS line in October 2026. Most production teams wait for LTS, so the upgrade window opens next month.

  1. May 5, 2026

    26.0.0 released as Current.
  2. May–Sep 2026

    Six months as Current, while library authors test against it.
  3. October 2026

    26 enters Long-Term Support.

Temporal, without a flag

The Temporal API is enabled by default. If you've shipped a bug where Date guessed a time zone, Temporal gives you separate types for a calendar date, a wall-clock time and an exact instant in a named zone:

// A meeting in Kyiv, shown to a colleague in New York.
const meeting = Temporal.ZonedDateTime.from(
  "2026-10-20T10:00[Europe/Kyiv]",
);
meeting.withTimeZone("America/New_York").toString();
// → "2026-10-20T03:00:00-04:00[America/New_York]"

// Date-only arithmetic, no time-zone surprises.
const dueDate = Temporal.Now.plainDateISO().add({ days: 14 });

That's the server. For client code, check Temporal's Baseline status on MDN, and keep a polyfill in the browser bundle until the browsers you support all ship it.

Two small additions

V8 moves to 14.6. Map.prototype.getOrInsert() replaces the get-check-set dance for grouping:

const postsByTag = new Map();
for (const post of posts) {
  for (const tag of post.tags) {
    postsByTag.getOrInsert(tag, []).push(post);
  }
}

getOrInsertComputed() takes a callback for defaults that cost something to build, and both methods exist on WeakMap too. Iterator.concat() joins iterators without spreading them into arrays first.

Removals

The semver-major list is long. These entries are the likeliest to break an app or one of its dependencies:

Selected semver-major changes from the 26.0.0 release notes
ChangeUse instead
http.Server.prototype.writeHeader() removedwriteHead()
_stream_readable, _stream_writable and the other stream* modules removedthe public node:stream API
--experimental-transform-types flag removeda build step, or type stripping without transforms
module.register() runtime-deprecatedplan a move to the newer hooks API
extensionless CommonJS exception removed for "type": "module" packagesgive CommonJS files a .cjs extension

Search for the _stream_* removal first. Your own code has little reason to import those modules, but an old dependency deep in the tree might. A plain grep for _stream_ matches the userland readable-stream package, which ships files with those names, so search for the imports themselves:

grep -rE "require\(['\"]_stream_|from ['\"]_stream_" node_modules

Readable streams changed too: readable.read() with no size now returns one buffered chunk instead of joining them. If your code depends on the old chunk sizes, cover it with a test before the switch.

Checklist

  1. Run the test suite on Node 26 in CI next to your current version.
  2. Search dependencies for _stream_ imports and writeHeader calls.
  3. Watch the logs for the new runtime deprecation warnings, module.register() among them.
  4. Move one server-side module that handles dates to Temporal, and drop the date library there if it holds up.
  5. Switch production after the October LTS release.

Sources

Volodymyr Chornous