Stable Release in branch 26.x
26.4.0
Released 24 Jun 2026
(3 days ago)
SoftwareNode.js
Version26.x
Status
Supported
Initial release26.0.0
05 May 2026
(1 month ago)
Latest release26.4.0
24 Jun 2026
(3 days ago)
End of bug fixes20 Oct 2027
(Ends in 1 year, 3 months)
End of security fixes30 Apr 2029
(Ends in 2 years, 10 months)
Release noteshttps://github.com/nodejs/node/releases/tag/v26.4.0
Source codehttps://github.com/nodejs/node/tree/v26.4.0
Documentationhttps://nodejs.org/dist/latest-v26.x/
Downloadhttps://nodejs.org/download/release/latest-v26.x/
Node.js 26.x ReleasesView full list

What Is New in Node.js 26

Category Highlights
New Features Temporal API enabled by default; experimental node:ffi module; crypto.randomUUIDv7(); fs.stat() signal option; http.IncomingMessage req.signal; http writeInformation() for arbitrary 1xx codes; fs.Stats / BigIntStats Temporal.Instant support; test_runner tag filtering and order randomization; node inspect runtime expression probes; util.styleText() hex color support; SQLite serialize/deserialize
Improvements V8 updated to 14.6 (Chromium 146) with Map upsert and Iterator.concat(); Undici updated to 8.3.0; stream.compose() marked stable; QUIC internal implementation completed with ALPN alerts and permission model support; crypto raw key format support; JWK support for ML-KEM and SLH-DSA; diagnostics_channel BoundedChannel; stream duplexPair destruction propagation; SQLite Percentile extension enabled; assert printf-style error messages; util.inspect() marks proxied objects
Breaking Changes Legacy _stream_* internal modules removed (end-of-life); http.Server.prototype.writeHeader() removed; --experimental-transform-types flag removed; module.register() runtime-deprecated; DEP0182 crypto API moved to end-of-life; localStorage returns undefined without a file; NODE_MODULE_VERSION bumped to 147; GCC minimum bumped to 13.2; Python 3.9 build support dropped; extensionless CJS exception removed for type:module packages
Deprecations DEP0203 and DEP0204 crypto APIs runtime-deprecated; DEP0201 stream API promoted to runtime deprecation; module.register() runtime-deprecated; Hmac.digest() documentation-only deprecation (DEP0206)

What Is New in Node.js 26?

Node.js 26 is a major release that ships the Temporal API as a first-class runtime feature, advances the V8 engine to version 14.6 (Chromium 146), introduces an experimental FFI module, and cleans up a large set of long-deprecated legacy internals. It will enter LTS in October, making this the right moment to start evaluating upgrade impact in your projects.


Is the Temporal API Finally Ready for Production in Node.js 26?

Yes -- the Temporal API is now enabled by default in Node.js 26 and no flag is required. Temporal is the long-awaited modern replacement for the Date object: it is immutable, has first-class timezone support, and handles calendar arithmetic correctly. If you have been reaching for libraries like date-fns or Luxon solely to compensate for Date quirks, Temporal is worth a serious look.

In practice, Temporal.Instant, Temporal.ZonedDateTime, and Temporal.PlainDate cover the vast majority of server-side date-handling tasks. Node.js 26.2.0 added a deeper integration point: fs.Stats and BigIntStats now expose timing fields as Temporal.Instant values, letting you write stat.mtimeInstant without a conversion step.

// Temporal in Node.js 26 -- no flag needed
const now = Temporal.Now.zonedDateTimeISO();
console.log(now.toString());
// 2026-06-07T10:30:00+07:00[Asia/Ho_Chi_Minh]

// fs.Stats Temporal integration (26.2.0+)
import { stat } from 'node:fs/promises';
const s = await stat('./package.json');
console.log(s.mtimeInstant.toString());
// 2026-06-01T04:22:10.123456789Z

Watch out for: Temporal requires Rust to be present in the build toolchain. When building Node.js from source, make sure cargo and rustc are available. Prebuilt binaries ship with Temporal enabled out of the box.


What Does V8 14.6 Bring to Node.js 26?

V8 14.6 (Chromium 146) is the JavaScript engine powering Node.js 26. This version ships two newly graduated TC39 proposals directly into the runtime without any flag.

  • Map / WeakMap upsert (Stage 4): Map.prototype.getOrInsert(key, defaultValue) and Map.prototype.getOrInsertComputed(key, callbackFn) eliminate the common if (!map.has(k)) map.set(k, ...) boilerplate. This matters if you build caches, memoization layers, or grouping logic using plain Maps.
  • Iterator sequencing: Iterator.concat(...iterables) lazily chains any number of iterables into a single iterator. No array spread needed -- memory stays flat.
// Map upsert
const cache = new Map();
cache.getOrInsert('key', 'default');       // returns 'default', inserts it
cache.getOrInsertComputed('k2', () => expensiveCompute());

// Iterator.concat
const combined = Iterator.concat([1, 2], [3, 4], [5]);
console.log([...combined]); // [1, 2, 3, 4, 5]

The NODE_MODULE_VERSION jumped to 147, meaning any native addon compiled against an earlier Node.js version must be recompiled. Most teams using node-gyp or prebuild pipelines should account for a rebuild step in their upgrade checklist.


How Does the New node:ffi Module Work in Node.js 26?

Node.js 26.1.0 ships an experimental node:ffi module that lets JavaScript call native shared libraries directly -- without writing a native addon or using a third-party package like ffi-napi. It is gated behind the --experimental-ffi flag and, when the Permission Model is active, also requires --allow-ffi.

// node --experimental-ffi app.mjs
import { DynamicLibrary, FFIType } from 'node:ffi';

const lib = new DynamicLibrary('libc.so.6');
const strlen = lib.get('strlen', FFIType.u64, [FFIType.pointer]);

const buf = Buffer.from('hello\0');
console.log(strlen(buf)); // 5n

This API is inherently unsafe. Passing an incorrect pointer, a mismatched type signature, or accessing memory after it has been freed can crash the process silently or corrupt heap state. The team added Symbol.dispose support to DynamicLibrary so you can use using declarations to ensure the library is unloaded deterministically. Most teams should treat this as a lower-level escape hatch for integrating system libraries, not a replacement for well-tested native addons in production-critical paths.


What Breaking Changes and Removals Should You Watch for in Node.js 26?

Node.js 26 finalizes the removal of several APIs that had been deprecated for multiple release cycles. The upgrade impact is low for greenfield code, but legacy codebases may need targeted edits.

  • _stream_* legacy internal modules removed: The internal _stream_wrap, _stream_readable, _stream_writable, _stream_duplex, _stream_transform, and _stream_passthrough modules are gone. Code that require()'d these directly (even through a transitive dependency) will throw. Migrate to the public node:stream API.
  • http.Server.prototype.writeHeader() removed: This was an old alias for writeHead(). Do a global find-and-replace; no logic change is needed.
  • --experimental-transform-types removed: TypeScript stripping is now stable in Node.js. The experimental flag is gone -- remove it from your package.json scripts.
  • module.register() runtime-deprecated: The hook-based custom loader API introduced as an experimental replacement for --loader is now flagged for replacement. Watch for the successor API.
  • localStorage returns undefined without a file: Previously this could throw. If any code conditionally relies on typeof localStorage, the behavior has changed.
  • Extensionless CJS exception removed for type:module packages: Packages with "type": "module" can no longer load extensionless CJS files. Add explicit .cjs extensions where needed.

Build environment changes also matter: the minimum GCC version is now 13.2, Python 3.9 is no longer supported for building Node.js from source, and the minimum Windows SDK is now version 11.


What Improvements Landed in Node.js 26 for HTTP, Crypto, and Testing?

Beyond the headline features, Node.js 26 delivers a focused set of quality-of-life improvements across the HTTP, crypto, and test runner subsystems that teams will benefit from in day-to-day development.

HTTP: http.IncomingMessage now exposes a req.signal property (an AbortSignal) so you can cleanly cancel in-flight request handling using standard Web API conventions. Node.js 26.2.0 added res.writeInformation(statusCode, headers) for sending arbitrary 1xx informational responses (think 103 Early Hints without workarounds). The ClientRequest options merge was also hardened to prevent prototype pollution.

Crypto: The biggest addition is crypto.randomUUIDv7() for generating time-ordered UUIDs. Compared to UUIDv4, v7 IDs sort lexicographically and are friendlier to B-tree indexes in databases -- a common pain point when using random UUIDs as primary keys. The crypto module also gained raw key format support in KeyObject APIs and JWK support for post-quantum key types (ML-KEM, SLH-DSA).

import { randomUUIDv7 } from 'node:crypto';

// Time-ordered, database-friendly UUIDs
const id = randomUUIDv7();
console.log(id); // e.g. 01970000-0000-7xxx-xxxx-xxxxxxxxxxxx

Test runner: The built-in test runner received several useful additions in v26.1.0 and v26.2.0: test order randomization via --test-random-order, tag-based filtering with --test-name-tag, mock-timer support for AbortSignal.timeout, and OTel-compatible diagnostics channel publishing. If your team has been hesitant to adopt the native test runner, these additions close several gaps.

FAQ -- Common Questions about Node.js 26

Does upgrading to Node.js 26 break existing native addons?
Yes, native addons must be recompiled because the NODE_MODULE_VERSION was bumped to 147. Any prebuilt binary for an earlier Node.js version will not load. Run npm rebuild or re-download prebuilds for packages like bcrypt, sharp, or canvas before deploying.

Is the Temporal API stable enough to use in production in Node.js 26?
Temporal is enabled by default and its implementation tracks the TC39 specification closely. It is not marked as experimental in Node.js 26, but the underlying spec still has a small number of open normative issues. For new greenfield date logic it is a solid choice; for critical financial or calendar calculations in existing codebases, consider a phased rollout alongside thorough test coverage.

How do I enable the node:ffi module?
Pass the --experimental-ffi flag when starting Node.js, for example: node --experimental-ffi app.mjs. If you are using the Permission Model you must also pass --allow-ffi to permit FFI calls. Because the module is inherently unsafe, it is not enabled in production server environments without explicit opt-in.

What replaces the removed _stream_* internal modules?
Use the public node:stream module. For example, replace any require('_stream_readable') with import { Readable } from 'node:stream'. The public API has been equivalent for many years; the internal modules were always a private implementation detail that leaked into userland code.

How does crypto.randomUUIDv7() differ from randomUUID()?
randomUUID() generates a version 4 UUID which is entirely random and has no sortable structure. randomUUIDv7() embeds a millisecond-precision timestamp in the high bits, making generated IDs monotonically increasing within the same millisecond and fully sortable. This is significant for database primary keys because sorted inserts avoid B-tree page splits and improve index locality. Note that the clock used is not guaranteed to be monotonic across process restarts.

Is module.register() being removed in Node.js 26?
It is runtime-deprecated in Node.js 26, meaning it will emit a deprecation warning at runtime but is not yet removed. The Node.js team is working on a successor API. Existing custom loader setups will continue to function in this release cycle, but you should plan a migration before the eventual removal in a future major version.

Releases In Branch 26.x

VersionRelease datenpm version
26.4.024 Jun 2026
(3 days ago)
11.17.0
26.3.117 Jun 2026
(10 days ago)
11.16.0
26.3.001 Jun 2026
(26 days ago)
11.16.0
26.2.020 May 2026
(1 month ago)
11.13.0
26.1.006 May 2026
(1 month ago)
11.13.0
26.0.005 May 2026
(1 month ago)
11.12.1