Deno 2.9 Ships 1.98x Faster Cold Start, 2.2-3.1x Less RSS Under Load, Default-On npm Minimum Release Age, No-Downgrade Trust Policy, and Built-In Snapshot Testing

Deno 2.9 Ships 1.98x Faster Cold Start, 2.2-3.1x Less RSS Under Load, Default-On npm Minimum Release Age, No-Downgrade Trust Policy, and Built-In Snapshot Testing

lschvn

Deno 2.9 shipped on 2026-06-25, published by Bartek Iwańczuk with the release notes on deno.com and the GitHub releases API listing v2.9.0. It is the largest Deno release of the cycle and the first tagged build that includes the deno desktop subcommand (the June 16 PR #33441) as well as a long list of supply chain, performance, test runner, web platform, and Node.js compatibility changes. The blog post opens with three numbers that anchor the release: cold start drops from 34.2 ms to 17.3 ms (1.98x), peak resident set on Deno.serve drops 2.2x on the realworld workload and 3.1x on 1 MiB bodies, and Deno.serve throughput climbs 1.27x realworld, 1.11x plaintext, and 1.18x on 1 MiB bodies. Behind those numbers are four primary perf changes (#34450, #35373, #35338, #35183), plus a new Deno-owned HTTP/1.1 serving path (#34446) and Rust ports of crypto.subtle (#34966) and console / Deno.inspect (#35087).

The 2.9 release follows Deno 2.8 on June 1, which focused on audit fixes, CI tooling, and the pack subcommand. The 2.9 cycle is a different shape: 165+ PRs land, the perf wins are the largest single-cycle jump in two years, and the supply chain work closes the gap with pnpm's minimumReleaseAge and pnpm's trustPolicy defaults.

Cold start, memory, and throughput

The headline numbers come from Deno's own benchmark harness, which runs three Deno.serve workloads at concurrency 100 against Deno 2.8.0 on a dedicated x86_64 Linux box, with server and load generator pinned to disjoint cores and oha median of 3 runs. Cold start is the mean of 150 hyperfine runs of a hello-world program. The full set:

WorkloadDeno 2.8Deno 2.9Change
Cold start (lower is better)34.2 ms17.3 ms1.98x faster
Deno.serve realworld (req/s, higher is better)56.8k72.4k1.27x
Deno.serve plaintext (req/s)77.0k85.6k1.11x
Deno.serve 1 MiB body (req/s)1,6171,9071.18x
RSS, realworld (lower is better)142 MB64 MB2.2x less memory
RSS, 1 MiB body197 MB63 MB3.1x less memory

The cold start drop is the most striking single number. The win comes from four primary changes. First, lazy-loading node: globals out of the snapshot so the snapshot itself is smaller (#34450). Second, gating the eager Node bootstrap to Node workers, so the main isolate no longer pays the bootstrap cost for code that never touches node: (#35373). Third, a V8 code cache for residual lazy-loaded ESM modules so the second startup skips the parse-and-compile step (#35338). Fourth, a minified snapshot that compresses the on-disk image (#35183). On macOS, chained fixups trim additional pre-main time (#35409).

The HTTP throughput gains ride on a new Deno-owned HTTP/1.1 serving path that replaces the hyper-based path Deno has shipped since 1.x (#34446). The two Rust ports are smaller but consequential: crypto.subtle (#34966) and console / Deno.inspect (#35087) move from JavaScript into Rust, trimming per-call overhead with no change in behavior. The WebCrypto port is the prerequisite for the WebCrypto Modern Algorithms work that lands the same release.

The memory flatness under load is the most consequential change operationally. In 2.8, RSS grew with the workload, from roughly 94 MB serving plaintext up to 197 MB streaming 1 MiB bodies. In 2.9 it stays essentially flat, holding around 62 MB no matter what the server is doing. That works out to 2.2x less peak RSS on the realworld workload and 3.1x less on 1 MiB bodies, so the same machine can run far more concurrent Deno.serve instances before it runs out of headroom. The team flags this as the standout of the cycle.

Supply chain hardening

The second headline is supply chain hardening, and it is the part of 2.9 that maps most directly onto the Axios npm supply chain attack from March and the Red Hat / Shai-Hulud npm attack from early June.

npm minimum-release-age, default-on. PR #35458 enables minimum-release-age by default with a 24h window. The setting was introduced in Deno 2.6 and was already a documented feature, but in 2.9 it is on by default. The premise is straightforward: a large class of npm supply chain attacks is caught simply by waiting, because a malicious version is usually detected and unpublished within a day or two of being released. A 24h window rejects most of them at install time. The default sits at the bottom of the precedence chain, so anything set explicitly in .npmrc wins: min-release-age=72h extends the window, min-release-age=0 opts out entirely. This is the same defense that pnpm shipped in 9.x and that Bun shipped in 1.x. Deno is the third major package manager to default it on.

no-downgrade trust policy, opt-in. PR #34927 adds the trust policy Deno has been missing. It ranks each package version by trust evidence: staged publishing (a maintainer approving a publish with a live 2FA challenge), trusted publishing backed by a provenance attestation, a provenance attestation on its own, and finally a plain token publish. With trust-policy=no-downgrade in .npmrc, Deno refuses to resolve a version whose trust evidence is weaker than the strongest evidence on any earlier-published version of the same package, compared by publish date. If a package has consistently shipped through trusted publishing or with provenance and a later version suddenly appears as a plain token publish (the hallmark of a compromised maintainer token, as in the August 2025 s1ngularity incident that extended into the Axios npm supply chain attack and the Red Hat / Shai-Hulud npm attack), the install becomes a hard error instead of a silent downgrade. The policy follows pnpm's design, and Deno ships two escape hatches that mirror pnpm: trust-policy-ignore-after (in minutes) skips the check for older, genuinely pre-provenance releases, and trust-policy-exclude[]=package exempts named packages. The policy is off by default because provenance and trusted publishing are still unevenly adopted across the registry.

Lockfile interop. The supply chain story extends to lockfiles. On the first deno install in a project that has a package-lock.json, pnpm-lock.yaml, yarn.lock, or bun.lock but no deno.lock, Deno seeds a fresh deno.lock straight from it, carrying over the exact resolved versions and integrity hashes (#34296, #35330, #35346, #35350, #35394). For pnpm workspaces, the separate pnpm-workspace.yaml is auto-migrated into package.json (or deno.json) without disturbing comments or existing fields (#34993). For a deno.lock that already contains git merge conflict markers from a botched rebase, Deno now resolves them automatically, unioning the additive sections and taking the higher version on genuine specifier conflicts (#34726). The combination means switching a Node project to Deno takes a couple of commands and preserves the existing dependency graph exactly.

Test runner parity with Vitest / Jest

The test runner work closes the Vitest / Jest feature gap that has been the most-cited reason teams stick with a Node-hosted test framework even when they like Deno for production code.

Built-in snapshot testing. PR #35139 adds t.assertSnapshot() to the test context, using the same format and serializer as @std/testing/snapshot with no import required. Snapshots are written to __snapshots__/test_file.snap next to the test; on a mismatch the runner prints a diff and tells you how to update (deno test --update-snapshots). Default-location snapshots need no read/write permissions (the runner manages them), and stale entries are pruned automatically when a full run updates them. Snapshot testing also works through node:test, via t.assert.fileSnapshot() (#35478).

Deno.test.each. PR #34938 registers one real, independently-filterable test per row of inputs. Array cases are spread as positional arguments; object cases are passed as a single argument and can be interpolated into the test name with $key. Name templates support printf-style tokens (%s, %i/%d, %f, %j, %o), %# for the case index, and $key.nested for nested object access. Deno.test.only.each and Deno.test.ignore.each compose as expected.

deno test --shard. PR #35057 splits the discovered test files into balanced groups for CI fan-out. It drops straight into a GitHub Actions matrix; the index is 1-based, sharding happens before --shuffle, and over-sharding (more shards than files) simply leaves some shards empty and exits cleanly. The trade-off the PR is explicit about: the shard is selected at run time, after the module graph for the full suite has been built and type-checked, so every machine still pays the graph-build and type-check cost for the whole suite. Moving the shard pre-filter ahead of type-checking is a natural follow-up.

Retry and repeats. PR #35053 adds retry: N and repeats: N options either per-test or across the whole run. A test that only passes after a retry is reported as flaky in the summary, so the signal is not silently lost. Per-test options take precedence over the CLI flags (including an explicit 0 to opt a test out).

Change-aware test selection. PR #35199 adds deno test --changed (tests affected by uncommitted changes), deno test --changed=origin/main (tests affected since branching off main), and deno test --related=src/util.ts (tests that depend on a specific file). Selection is dependency-aware (it walks the module graph, across workspace members) and conservative: changing config, lockfile, import map, or package.json disables filtering and runs everything.

Coverage thresholds. PR #35056 lets coverage fail a run when it drops below a target, either via --threshold=90 or configured per-metric in deno.json (lines, branches, functions). When the aggregate falls short, the command exits non-zero and tells you which metric missed.

deno desktop ships as the first tagged build

The deno desktop subcommand that merged as PR #33441 on June 16 ships in Deno 2.9 as the first tagged build with the feature. The June 16 article covers the architectural piece (WEF backend, CEF default, webview / raw alternates, Deno.BrowserWindow API, framework auto-detection for Next.js / Astro / Fresh / Remix / Nuxt / SvelteKit / SolidStart / TanStack Start / Vite SSR, CDP multiplexer for unified DevTools across two V8 isolates, auto-updater with bsdiff patches, cross-compile). The 2.9 release adds the practical pieces that turn the PR into something you can ship:

  • Default UI backend is webview (#35442), so binaries stay small and launch fast. --backend cef opts into bundled Chromium for guaranteed-identical rendering on every platform.
  • Native Wayland instead of XWayland on Wayland systems (#35485). The June 16 PR was X11-only and ran Wayland sessions through XWayland; the 2.9 cycle lifts that limit.
  • Linux .deb and .rpm installer output formats (#35296), produced from any host with no platform-specific packaging toolchain.
  • Windows .msi installer output format (#35378), the same.
  • Autodetect Vite framework (#35470), on top of the Next / Astro / Fresh / Remix / Nuxt / SvelteKit / SolidStart / TanStack Start list.
  • Bluetooth usage descriptions and macOS desktop Info.plist keys (#35472, #35484), for App Store submission readiness.
  • Bundled libc++ symbols hidden (#35424) so the desktop runtime can be dlopen'd on Linux.
  • --compress for self-extracting app bundles (#35420), which unpacks on first launch and shrinks artifact size for npm-heavy projects.

The full guide lives at docs.deno.com/runtime/manual/desktop, and denidian, a note-taking app built with deno desktop, is published alongside as the reference example.

WebCrypto Modern Algorithms

The WebCrypto work is the same family of work as the Node.js 24.18.0 'Krypton' LTS Web Crypto piece and the Node.js 26.4.0 'Current' WebCrypto cSHAKE work: the Modern Algorithms in the Web Cryptography API proposal starting with NIST's post-quantum algorithms.

  • ML-KEM (FIPS 203) key encapsulation: ML-KEM-512, ML-KEM-768, ML-KEM-1024 (#34447). Adds four new crypto.subtle methods: encapsulateKey / encapsulateBits and decapsulateKey / decapsulateBits.
  • ML-DSA (FIPS 204) signatures: ML-DSA-44, ML-DSA-65, ML-DSA-87, including JWK import/export (#34448, #34914).
  • SLH-DSA (FIPS 205) signatures, all twelve parameter sets (#35223).
  • ChaCha20-Poly1305 AEAD (#34417).
  • SHA-3 family and XOFs: SHA3-256, SHA3-384, SHA3-512, SHAKE128, SHAKE256, cSHAKE, TurboSHAKE, KangarooTwelve.
  • KMAC and Argon2 key derivation.

A new synchronous SubtleCrypto.supports() feature-detection method (#34903) lets user code test for support at runtime: SubtleCrypto.supports("sign", "ML-DSA-65") returns true on a 2.9 build. The entire crypto.subtle implementation was ported from JavaScript to Rust (#34966), trimming per-call overhead with no change in behavior, which is the prerequisite for the post-quantum work landing in the same release.

Node.js compatibility advances to 26

Deno 2.9 advances its Node.js compatibility target to Node 26. The reported process.version moves to v26.3.0 (#34747), and the node-compat test suite Deno runs against is bumped to 26.3.0 (#34746). Bare Node builtins now resolve without configuration: import fs and import path map to node:fs / node:path unconditionally, with no --unstable-bare-node-builtins flag (#33316). This also fixes a bug where a node_modules package could shadow a builtin; builtins now always win, while deno.json imports and package.json dependencies mappings still take precedence.

The node:test gains are a meaningful piece on their own: mock.module() and mock.timers (#35329, #33946), t.assert.fileSnapshot() (#35478), and TestContext.runOnly() (#35158). The runner now fails on unhandled rejections, enforces timeouts, and runs hooks in the correct order (#35297, #35393). More runtime APIs: process.resourceUsage() (#35468) and worker_threads.isInternalThread (#35234) are now implemented, and AsyncLocalStorage context is preserved across node:net callbacks (#35237). Deno's NAPI implementation now reports version 10 (#35270), in line with Node 26. The Web Storage / KV persistence (#34618) for deno compile outputs and the preferPackageJson setting (#35392) are the same compatibility-driven ergonomics work, now stabilized.

Lockfile interop and dependency management

The lockfile work is the part of 2.9 most directly aimed at letting Node projects switch to Deno. The five lockfile-reading PRs (#34296, #35330, #35346, #35350, #35394) together mean that running deno install in a project with a package-lock.json, pnpm-lock.yaml, yarn.lock, or bun.lock produces a deno.lock that preserves the exact resolved versions and integrity hashes from the existing lockfile. There is no re-resolution and no surprise upgrades: the versions the user was running under npm are the versions they run under Deno. From there deno install writes a node_modules directory Deno can run against, and deno task runs the package.json scripts they already have, so the rest of a team can keep working the way they do.

For pnpm workspaces, the separate pnpm-workspace.yaml is auto-migrated into package.json (or deno.json) without disturbing comments or existing fields (#34993). Combined with the catalog: protocol Deno adopted in 2.8, centralized, shared dependency versions keep working after the move. For deno.lock files that already contain git merge conflict markers from a botched rebase, Deno now resolves them automatically, unioning the additive sections and taking the higher version on genuine specifier conflicts (#34726). When a node_modules directory is in use, the new opt-in jsrDepsInNodeModules setting installs jsr: dependencies into it through JSR's npm compatibility registry (#35029), matching how pnpm and npm already handle JSR packages.

The new dependency-management subcommands round out the picture. deno link and deno unlink (#34359) give first-class CLI access to the links array in deno.json (the npm-link-style workflow for local JSR packages). The links field itself is stable in 2.9: it shipped under that name back in 2.3 and was never gated behind a runtime flag, so 2.9 simply drops the remaining unstable labeling (#34996). deno list (#34972) prints the dependencies a project declares in deno.json and package.json and resolves their versions, the equivalent of npm ls / pnpm list. deno watch (#35301) is a short, more discoverable alias for deno run --watch-hmr main.ts that re-runs on file changes with hot module replacement, restarting if hot replacement fails.

deno fmt on the lax engines

deno fmt rebuilds on the new lax formatting engines, which only ever move whitespace: they never reorder, requote, or drop a token, and they pass malformed input through instead of erroring. HTML, XML, and SVG are now formatted by lax-markup, and they format by default with no flag (#35174). Component formats (Vue, Svelte, Astro, Vento, Nunjucks, Mustache) are available under --unstable-component. A 10 MB document that previously could not be formatted in 15 minutes now takes about a tenth of a second. CSS, SCSS, and Less are now formatted by lax-css (still under --unstable-css), which fixes a long list of parse errors and value-mangling bugs (#35160). Note that the indented .sass syntax is no longer supported. SQL formatting (under --unstable-sql) is now powered by lax-sql, which produces canonical, dialect-agnostic output (#35161).

Two new configuration options for JavaScript and JSON: sortNamedImports and sortNamedExports control how named specifiers are ordered (caseInsensitive (the default), caseSensitive, maintain (leave source order alone, handy for matching Biome's ordering)) (#33313); and json.trailingCommas controls trailing commas in JSON and JSONC (never, always, maintain, jsonc) (#33383). deno fmt now reads .editorconfig files and uses them to fill in any formatting options the user has not set explicitly, with precedence running CLI flags → deno.json → .editorconfig → built-in defaults (#34071).

deno task, deno compile, deno bundle

The task runner picks up input-based caching, concurrency control, and several new flags. Input-based caching: declare a task's inputs with files (and outputs with output), and Deno skips the task entirely when nothing relevant has changed, restoring any declared output artifacts straight from the cache (#34509). The fingerprint includes the command, the contents of files matched by files, the values of any env variables listed, the fingerprints of the task's dependencies, the host OS, the CPU architecture, and the Deno version. Arguments and env are part of the key: deno task build foo and deno task build bar cache independently, and changing a listed env value invalidates the cache. Dependencies cascade (a task re-runs when one of its dependencies re-ran, even if its own inputs are unchanged). Safe by default: if the files globs match nothing, the task is treated as uncacheable and always runs, so a typo can never produce a false cache hit. npm scripts and tasks without a command are never cached.

Controlling concurrency: --jobs (short -j, alias --concurrency) caps how many tasks run at once in a workspace run; --jobs 1 forces sequential execution; it overrides the DENO_JOBS environment variable and defaults to the number of available CPUs (#35318). Other flags: --if-present exits 0 instead of erroring when the named task does not exist, matching npm (#35315); --env-file loads a dotenv file into the tasks environment without forwarding the flag to every inner command (#34508); exclusion groups in task-name wildcards (deno task test:*(!e2e|interactive)) run every test:* task except the excluded ones (#34506).

deno compile gains --include-as-is, which embeds a file or directory into the executable's virtual filesystem without any module resolution or transpilation (#32417). Where --include runs files through the module graph, --include-as-is is for assets and pre-built bundles you just want available via filesystem APIs at runtime. The two flags combine, so you can resolve some modules and embed others verbatim in the same build. Compiled binaries also get real persistent storage: a default Deno.openKv(), localStorage, and the caches API now persist to a per-app directory under the platform's app-data location instead of falling back to in-memory storage (#34618). The storage identity is the new --app-name flag, which defaults to the output file name, so two binaries built with the same --app-name share a store. By default deno compile embeds the entire resolved node_modules tree into the binary; the new experimental --bundle flag instead runs the entrypoint through Deno's bundler first (tree-shaking and emitting a single module), which can dramatically shrink binaries for npm-heavy projects (a lodash hello-world dropped from 11.6 MB to 1.5 MB in Deno's own measurements). Pair it with --minify to shrink the embedded bundle further (#34527, #34532, #34536). deno compile also picks up --watch mode (#34860). deno bundle can now emit a rolled-up .d.ts alongside the bundled JavaScript with --declaration (#33838), and understands the object form of npm's package.json browser field when bundling with --platform browser (#34407).

Web platform and runtime additions

Six additions to the web platform surface ship in 2.9. The Web Locks API lands in full (#31166), letting you coordinate access to a named resource across async tasks and workers through navigator.locks.request("config", async lock => { /* exclusive access here until this callback resolves */ }), with shared vs exclusive modes, ifAvailable, steal, an AbortSignal, and navigator.locks.query() to inspect held and pending locks. Happy Eyeballs v2 (RFC 8305) lands in Deno.connect and Deno.connectTls (#31726), racing IPv6 and IPv4 addresses on dual-stack networks for faster, more reliable connections, on by default with autoSelectFamily: false to opt out or autoSelectFamilyAttemptDelay to tune the stagger (default 250ms). navigator.userAgentData ships in both window and worker scopes (#34743). RequestInit accepts the Fetch-standard priority member (auto, high, low) (#34716). Deno.watchFs supports an ignore option for paths like .git or build output (#31582). process.kill on the current process no longer requires --allow-run (#34382).

CSS module imports ship under --unstable-raw-imports (#35093), matching the CSS module scripts web standard: import sheet from "./styles.css" with { type: "css" }; returns a CSSStyleSheet instance, so the same code runs in Deno and in the browser without a bundler step. Stable --unsafe-proto (#34738, #35192) replaces the unstable flag, and when a program crashes after touching the disabled Object.prototype.__proto__ accessor, Deno suggests re-running with it. The WebAssembly ESM integration fix (#34912) unwraps global exports from imported .wasm modules, matching the WebAssembly/ESM spec and Node. Deno.serve no longer compresses response bodies automatically (#35253, #35486); enable it per server with automaticCompression: true, or process-wide with DENO_SERVE_AUTOMATIC_COMPRESSION=1. OpenTelemetry gains OTEL_TRACES_SAMPLER (with OTEL_TRACES_SAMPLER_ARG) for head-based sampling, OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT and OTEL_SPAN_EVENT_COUNT_LIMIT for per-span caps, and auto-instrumentation that now also traces node:http2 clients and servers (#34764, #34787, #34795, #34510).

What this release is doing to Deno's trajectory

The 2.9 cycle is the first time Deno has shipped three roughly co-equal headline categories in a single tagged build: a major perf jump (cold start, memory, throughput), a major supply chain hardening (default-on minimum-release-age, opt-in no-downgrade trust policy), and a major test runner feature drop (snapshot testing, parameterized tests, sharding, retries, change-aware selection, coverage thresholds). The desktop subcommand that merged as PR #33441 on June 16 finally ships as the first tagged build, the lockfile interop work means a Node project can switch to Deno with a couple of commands and a preserved dependency graph, and the WebCrypto Modern Algorithms work puts Deno on the same post-quantum cryptography track as Node 24 LTS and Node 26 Current.

The pieces that the team has flagged as the next Deno release candidates are visible from the PR descriptions: sharding ahead of type-checking (#35057's trade-off), Web Locks API expansion (timeouts, steal with timeout), the no-downgrade trust policy gaining per-package overrides beyond the existing trust-policy-exclude[] array, and deno fmt graduating the lax engines from unstable to stable. The full list of 165+ PRs in the 2.9 cycle is on the Deno 2.9.0 GitHub release.

Frequently Asked Questions

Related articles

More coverage with overlapping topics and tags.

Node.js 24.18.0 'Krypton' LTS Lands Buffer.poolSize at 64 KiB, Web Crypto's TurboSHAKE and KangarooTwelve, and http.writeInformation for Arbitrary 1xx Codes
runtimes

Node.js 24.18.0 'Krypton' LTS Lands Buffer.poolSize at 64 KiB, Web Crypto's TurboSHAKE and KangarooTwelve, and http.writeInformation for Arbitrary 1xx Codes

Node.js 24.18.0 'Krypton' (LTS), published 2026-06-23, ships the Buffer.poolSize 64 KiB default that landed on Current in 26.3.0, adds RFC 9861's TurboSHAKE and KangarooTwelve to Web Cryptography (PR #62183, 1,521 additions, 13 files), adds http.writeInformation for arbitrary 1xx status codes (PR #63155, 306 additions, 7 files), exposes V8 precise coverage start to the JS inspector runtime (commit 8c989ec4a3), adds JWK import-export for the ML-KEM and SLH-DSA post-quantum key types (PR #62706, 842 additions, 39 files), lands the BoringSSL-side wiring of ML-DSA, ML-KEM, ChaCha20-Poly1305, and AES-KW for Web Crypto (PR #63255), hardens WebCrypto against prototype pollution (PR #63363), aligns crypto.diffieHellman key argument names and accepts key data inputs (PR #62527), reverts the 24.16.0 'noop pause/resume on destroyed streams' behavior (PR #63834), and ships a single-line hotfix on 22.23.1 that backs out an http agent change from the 06-18 security release that triggered an unexpected re-stream.
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
runtimes

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.
Bun Integrates the React Compiler Directly Into Its Bundler, Roughly 20x Faster Than the Babel Plugin
performance

Bun Integrates the React Compiler Directly Into Its Bundler, Roughly 20x Faster Than the Babel Plugin

PR #32504, merged into oven-sh/bun on June 20, 2026, turns the upstream React Compiler Rust port into a built-in `bun build` transform behind `--react-compiler` and `Bun.build({ reactCompiler: true })`. Bun ports the upstream `facebook/react` `compiler/crates/` workspace directly into a single `src/react_compiler/` crate (~62k LOC) instead of going through Babel, SWC, or Oxc, and on a large React codebase (around 860 components, 1400 memo slots) the compiler pass runs in 465 ms versus 9.15 s for the Babel plugin. The feature is experimental, off by default, and ships with `reactCompilerOutputMode` (client or ssr) and a `scripts/sync-react-compiler.sh` re-sync helper.

Comments

Log in Log in to join the conversation.

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