
Node.js v25.4.0: require(esm) goes stable, plus a proxy helper
I have watched more Node upgrades fail on “ESM weirdness” than on actual bugs.
Node.js v25.4.0 (released 2026-01-19) moves a few long-awaited pieces from “experimental” to “stable,” and it sneaks in a global proxy helper that will save you a pile of boilerplate in locked-down networks.
What actually changed in v25.4.0
Here’s the short list I care about when I run a runtime bump through staging.
Node v25 is a Current line, so I treat it like a fast-moving train. I test it hard, then I decide.
- require(esm) is now stable: Node marked require(esm) stable in v25.4.0. This matters if your repo still has CommonJS entry points but you have started importing ESM-only packages.
- Module compile cache is now stable: Node stabilized the module compile cache feature, which targets faster startup by reusing compiled output across runs.
- New http.setGlobalProxyFromEnv(): Node added http.setGlobalProxyFromEnv() so apps can pick up HTTP_PROXY and HTTPS_PROXY without hand-rolling agent code.
- CLI flag is stable now: Node marked –heapsnapshot-near-heap-limit as stable, useful when you chase memory cliffs in production.
- events.listenerCount() got broader: events.listenerCount() now accepts EventTargets, not just EventEmitters, so browser-style targets no longer feel like second-class citizens in Node code.
- Small util helper: util.convertProcessSignalToExitCode() helps you map signals like SIGTERM to the exit codes you log and alert on.
- Root cert refresh: Node updated bundled root certificates to NSS 3.117, which can change TLS trust outcomes if you rely on old corporate chains.
The thing that bit me before: CommonJS and ESM in the same repo
Interop breaks at 2 a.m.
You bump Node, a dependency flips to ESM-only, and suddenly your CommonJS service dies on boot with a loader error that nobody wants to read. v25.4.0 making require(esm) stable does not remove all the sharp edges, but it does mean Node considers the behavior part of the supported surface now.
My rule: if you run mixed module systems, you should test the exact entry points you deploy, not just “npm test.”
That includes the CLI you use in prod, the same Docker base image, and the same env vars. I have not tested this with every bundler and loader hook combo, so if you run custom loaders, you should assume extra work.
Global proxy setup without the agent spaghetti
🔔 Never Miss a Breaking Change
Get weekly release intelligence — breaking changes, security patches, and upgrade guides before they break your build.
✅ You're in! Check your inbox for confirmation.
This one saves time.
In corporate networks, I often see teams copy-paste 40 lines of proxy-agent setup into every service. v25.4.0 adds http.setGlobalProxyFromEnv() so you can make Node read HTTP_PROXY and HTTPS_PROXY once, at process start.
- How you use it: Call http.setGlobalProxyFromEnv() as early as you can, before you create clients that cache agents.
- What to watch: Confirm your container or system actually exports HTTP_PROXY and HTTPS_PROXY at runtime, not just in your CI job.
If your outbound traffic goes through a proxy, validate CONNECT behavior in staging. Do not discover proxy auth failures in production.
Performance notes: treat “faster” as a hypothesis
Ignore vanity claims.
I do not trust “performance improvements” until I see p95 latency, CPU, and RSS in my own workload. Node v25.4.0 includes targeted improvements in assert and Buffer paths, but your app might never touch those hot paths.
- Good fit: Test suites and services that do lots of deep comparisons (assert-heavy code) might see wins.
- Probably no change: If you spend 80% of your time waiting on Postgres, you will not feel this release.
Who should upgrade, and who should probably wait
It depends.
If you need stable require(esm) or you want the proxy helper, v25.4.0 gives you a concrete reason to move. If you just want “latest Node,” I would rather see you on an LTS line for production unless you already run Current across the fleet.
- Upgrade sooner: Mixed CommonJS and ESM repos, proxy-heavy environments, teams actively testing Current releases.
- Wait or canary only: Apps with native addons you dread rebuilding, teams pinned to strict base images, or anyone who cannot roll back quickly.
Upgrade plan I use in real life
Do not yolo prod.
For a dev sandbox, sure, install it and move on. For production, I do the boring stuff because boring keeps pagers quiet.
- Step 1, pin the runtime: Update your toolchain to use 25.4.0 explicitly, for example nvm install 25.4.0 and nvm use 25.4.0.
- Step 2, rebuild dependencies: Run npm ci or yarn install in a clean workspace so native modules rebuild against the new runtime.
- Step 3, run a smoke boot: Start the service with the same flags you use in prod, then hit one endpoint. Watch the logs for loader and TLS errors.
- Step 4, canary it: Route a small slice of traffic to the new runtime, watch error rate and memory for 24 to 48 hours, then roll forward.
- Step 5, keep a rollback ready: Preserve the previous Node image tag or version pin so you can revert in minutes, not hours.
Known issues
The release notes do not list known issues for v25.4.0.
That does not mean you will not find one. Anyway.
Official release notes
Read the upstream changelog before you schedule the rollout. It has the PR links you will want during debugging.
https://nodejs.org/es/blog/release/v25.4.0
Keep Reading
- Node.js Release History
- Node.js v25.5.0 Release Notes: –build-sea and Safer SQLite Defaults
- Node 20 vs 22 vs 24: Which Node.js LTS Should You Run in Production?
- Node.js v22.22.0 TLSSocket errors: why your app stops crashing (and why that scares me)
- VS Code 1.108.0 release notes: housekeeping, real changes, and a sane upgrade plan
Frequently Asked Questions
Is require(esm) stable in Node.js 25.4.0? Yes. Node.js v25.4.0 marked require(esm) as stable, meaning you can now use require() to load ES modules from CommonJS code without experimental flags. This is significant for projects that mix CommonJS entry points with ESM-only dependencies, which is increasingly common as the npm ecosystem shifts toward ESM.
What is http.setGlobalProxyFromEnv() in Node.js 25.4.0? A new built-in function that configures HTTP and HTTPS clients to use proxy settings from environment variables (HTTP_PROXY, HTTPS_PROXY, NO_PROXY). Previously, you had to manually create proxy agents or use third-party packages. This is especially useful for corporate environments and CI runners behind firewalls.
Should I use Node.js 25 in production? Node.js 25 is a Current (non-LTS) release line, which means it gets new features faster but has a shorter support window and no long-term maintenance. Use it in production only if you are comfortable with the faster upgrade cadence. For stability-focused environments, wait for Node.js 26 LTS or stay on Node.js 22 LTS.
Does the root certificate update in Node.js 25.4.0 affect TLS connections? Potentially. The update to NSS 3.117 root certificates can change which certificate authorities Node trusts. If your services connect to endpoints using certificates signed by recently added or removed CAs, TLS handshakes may succeed or fail differently. Test outbound HTTPS connections to third-party APIs after upgrading.