Node.js 25.9: The stream/iter API Finally Lands as Experimental

Node.js 25.9: The stream/iter API Finally Lands as Experimental

lschvn5 min read

Node.js 25.9.0 dropped on April 1st with a batch of quality-of-life additions, several of which have been in the making for over a year. The headline features are the new experimental stream/iter module and the --max-heap-size CLI flag, but there's more worth knowing about.

stream/iter: Async Iteration for Streams

The new experimental/streams/iter module (to be promoted to stable in a future release) adds two functions:

  • stream.iter(readable), returns an async iterator that yields chunks from a Readable stream
  • stream.consume(readable), creates a writable stream that drains a readable, useful for piping patterns

The practical effect is that you can now use for await...of directly over any Node.js Readable stream:

import { iter } from 'node:experimental/streams/iter';
import { createReadStream } from 'node:fs';

for await (const chunk of iter(createReadStream('file.txt'))) {
  process(chunk);
}

This replaces the Readable.from() workaround that many developers used to bridge streams and async iterables. Readable.from() was designed to create a stream from an iterable, using it as a stream consumer was always a hack. The new API makes the intent explicit and avoids the double-buffering overhead of the old pattern.

The consume() function is oriented toward transforming streams:

import { consume } from 'node:experimental/streams/iter';
import { createReadStream, createWriteStream } from 'node:fs';

const writable = createWriteStream('output.txt');
await consume(createReadStream('input.txt')).pipe(writable);

James M Snell, who implemented the feature, also added benchmarks in the same PR, the API is designed to have minimal overhead compared to manual stream consumption.

--max-heap-size: Hard Memory Bounds

Node.js processes have always been subject to V8's heap limits, but setting them required either environment variables (--max-old-space-size) or programmatic APIs. --max-heap-size is a straightforward CLI flag:

node --max-heap-size=512 server.js

Unlike --max-old-space-size, which controls only the old generation, --max-heap-size applies to V8's total heap including code generation and new generation. This makes it more predictable for containerized workloads where you want a hard memory ceiling that the orchestrator can rely on.

The flag was contributed by tannal and had been in discussion for several years before landing.

AsyncLocalStorage Gets Using Scopes

AsyncLocalStorage has been a staple for request-scoped context in web frameworks since Node.js 16. The new addition is support for using scopes, based on ECMAScript's Explicit Resource Management stage 3 proposal (the Symbol.dispose pattern).

The using keyword calls a Symbol.dispose method when a block exits, whether normally or via an error. With the new API, you can bind an AsyncLocalStorage instance to a scope:

import { AsyncLocalStorage } from 'node:async_hooks';

const storage = new AsyncLocalStorage();

{
  using scope = storage.enable();
  storage.run({ requestId: 'abc123' }, () => {
    // storage.get() returns { requestId: 'abc123' }
  });
}
// storage is automatically cleared when scope exits

This eliminates the need for explicit try/finally cleanup in many patterns. In high-throughput servers that create many short-lived storage instances, using scopes prevent the AsyncLocalStorage store from growing unboundedly.

Crypto: TurboSHAKE and KangarooTwelve

The crypto module gains two new hash functions via WebCrypto integration:

  • TurboSHAKE: variable-length output, suitable for streaming and tree hashing applications
  • KangarooTwelve: fast 128-bit hash, a SHA-3 derivative designed as a faster alternative to SHA-256 for everyday use cases

These are available through the standard WebCrypto SubtleCrypto.digest() interface under their respective algorithm names.

Other Notable Changes

  • Test runner mocking consolidated: MockModuleOptions.defaultExport and MockModuleOptions.namedExports merged into a single MockModuleOptions.exports option, with an automated codemod available
  • npm upgraded to 11.12.1: includes the latest npm features and security fixes
  • SEA code cache for ESM: Single Executable Applications now support code caching for ESM entry points, improving startup time for bundled Node.js applications
  • module.register() deprecated: the legacy module registration API is now formally deprecated (DEP0205)

Node.js 25 is the current unstable version line; Node.js 24 will become the next LTS candidate later this year. Most of these features will backport to LTS lines as they stabilize.

Frequently Asked Questions

Related articles

More coverage with overlapping topics and tags.

Node.js 26.4.0 'Current' Ships node:vfs Subsystem (Matteo Collina), ESM Loader Package Maps (Maël Nison), TLS Certificate Compression, TCP_KEEPINTVL/TCP_KEEPCNT, and argon2 Stable
security

Node.js 26.4.0 'Current' Ships node:vfs Subsystem (Matteo Collina), ESM Loader Package Maps (Maël Nison), TLS Certificate Compression, TCP_KEEPINTVL/TCP_KEEPCNT, and argon2 Stable

Node.js 26.4.0 (Current), published 2026-06-24 by @aduh95, lands eight SEMVER-MINOR changes: a minimal node:vfs subsystem that mounts user-supplied virtual filesystems (PR #63115, Matteo Collina) plus a follow-up that dispatches node:fs/promises to mounted VFS instances (PR #63537), package maps for ESM loaders that route bare specifiers through the loader hooks (PR #62239, Maël Nison), TLS certificateCompression that wires RFC 8879 zlib and zstd compression through the OpenSSL build config (PR #62217, Tim Perry), TCP_KEEPINTVL and TCP_KEEPCNT support in net.Socket.setKeepAlive (PR #63825, Guy Bedford), caller-supplied buffers in fs.readFile / fs.readFileSync (PR #63634, Matteo Collina), closeIdleConnections that now also drops pre-request sockets (PR #63470, semimikoh), net.BlockList advanced to Release Candidate stability (PR #63050), and crypto argon2 + KEM encap/decap marked stable (PR #63924, Filip Skokan). The release also adds WebCrypto cSHAKE (PR #63988), QUIC listEndpoints (PR #63536) and X509Certificate handles (PR #63191), dgram connectSync / bindSync (PRs #63838 + #63932, Guy Bedford), early-TCP net.BoundSocket (PR #63951), an experimental fast FFI call path for AArch64 and x86_64 (PRs #63068 + #63941, Paolo Insogna), npm 11.17.0 (PR #63857), sqlite 3.53.2, and libffi 3.6.0.
Node.js June 2026 Security Release: 12 CVEs Across v22.23.0, v24.17.0, and v26.3.1, with Two High-Severity TLS and Crypto Fixes
security

Node.js June 2026 Security Release: 12 CVEs Across v22.23.0, v24.17.0, and v26.3.1, with Two High-Severity TLS and Crypto Fixes

On June 18, 2026, the Node.js project shipped coordinated security releases for the v22 'Jod' LTS, the v24 'Krypton' LTS, and the v26 Current line. The drop fixes 12 CVEs, including two rated High: CVE-2026-48618 (TLS hostname normalization for server identity checks) and CVE-2026-48933 (WebCrypto cipher output length guard). The release also picks up OpenSSL 3.5.7, undici 8.5.0 on v26, llhttp 9.4.2, and nghttp2 1.69.0 (semver-major) on v22 and v24.
Claude Code Issue #74066: Users Report Cross-Workspace Context Bleed on Sonnet 5, Anthropic Has Not Yet Responded
security

Claude Code Issue #74066: Users Report Cross-Workspace Context Bleed on Sonnet 5, Anthropic Has Not Yet Responded

An open bug filed against Claude Code on 2026-07-04 by an [Enterprise ZDR](https://docs.anthropic.com/en/docs/build-with-claude/zero-data-retention) user describes a working session on Sonnet 5 that suddenly starts referencing an unrelated Minecraft temple build, then doubles down on the wrong task in its recap. The reporter (GitHub: [@milesrichardson-edb](https://github.com/milesrichardson-edb), issue [anthropics/claude-code#74066](https://github.com/anthropics/claude-code/issues/74066)) is on Enterprise Zero Data Retention, the tier Anthropic specifically advertises as session-isolated. Triage on the reporter's local session JSONL at `~/.claude/projects/<encoded-cwd>/<session-id>.jsonl` finds the leaked text is not in the transcript, ruling out a local context bleed by file overlap. Four other users in the comments (with work histories going back to last year) describe near-identical behavior across Claude Code, Claude Mobile, and Claude deep research. The most plausible architectural fit is shared KV-cache state in inference ([per @yv3nne in the comments](https://github.com/anthropics/claude-code/issues/74066#issuecomment-4880448776)), but no Anthropic engineer has commented on the issue in the 22 hours since it was filed, and the issue reached the top of [Hacker News](https://news.ycombinator.com/item?id=42481789) on 2026-07-04. The tone in the thread is split: half suspecting a real platform cache reuse, half suspecting a [sonnet-5-specific hallucination triggered by a Pygments lexer](https://github.com/anthropics/claude-code/issues/74066#issuecomment-4880334711). Both readings are credible.

Comments

Log in Log in to join the conversation.

No comments yet. Be the first to share your thoughts.