Node.js 22: New Features Every Developer Should Know

By Eoin Villarin, 2026-02-20, updated 2026-10-28

Node.js 22 brought type stripping, require(esm), a mature test runner and a WebSocket client. See which features are stable, their limits, and when to move to Node 24 or 26.

Which Node.js 22 features should developers use, and is Node 22 still supported?

The most useful Node.js 22 features are TypeScript type stripping, enabled by default from 22.18.0, require() for ES modules from 22.12.0, a mature built-in test runner, a browser-compatible WebSocket client, fs.glob and node --run. Node.js 22 is in Maintenance LTS until April 30, 2027, so new projects should start on Node.js 24 or 26.

Key takeaways

  • Type stripping was added in 22.6.0, enabled by default in 22.18.0 and marked stable in Node.js 24.12.0.
  • Type stripping skips type checking and rejects enums, so tsc --noEmit should still run in CI.
  • require(esm) works without a flag from 22.12.0, but throws if the module graph uses top-level await.
  • The node:test runner gained snapshot testing and module mocking in 22.3.0 and coverage thresholds in 22.8.0.
  • Node.js 26 is scheduled to become LTS on October 28, 2026 and is supported until April 2029.

The headline Node.js 22 features quietly changed how I set up JavaScript projects. Running TypeScript files without a build step, loading ES modules with require(), a test runner that covers most needs and a browser-compatible WebSocket client all arrived in the 22 release line, and several of them only became stable or unflagged in later 22.x updates.

That timing matters. Node.js 22 shipped in April 2024, but if you last checked its features at launch, you missed most of what makes it useful today. It is also no longer the newest LTS line, so you need to know where it stands before choosing it for a new project.

This guide covers where Node.js 22 sits in the release schedule in October 2026, the features worth adopting, the exact versions where each one became usable, their limitations, and whether you should upgrade to Node.js 24 or 26 instead.

Where do Node.js 22 features stand in October 2026?

Node.js 22, codename Jod, has been in Maintenance LTS since October 21, 2025, and reaches end of life on April 30, 2027. It still receives security fixes, and the latest release at the time of writing is 22.23.4. Here is how the supported lines compare, based on the official Node.js releases page and release schedule:

Close-up of a mechanical watch movement, a reminder that runtime support windows run out
Node.js 22 is in maintenance until April 2027. Photo: asternecky, CC0
VersionStatus in late October 2026End of lifeV8 engine
Node.js 22 (Jod)Maintenance LTSApril 30, 202712.4
Node.js 24 (Krypton)Maintenance LTS since October 20, 2026April 30, 202813.6
Node.js 26Current, scheduled to become LTS on October 28, 2026April 30, 202914.6

There is also a schedule change ahead. Node.js 26 is the last line under the twice-yearly model. Starting with Node.js 27, the project moves to one major release per year, released in April and promoted to LTS in October.

How to run TypeScript directly with Node.js type stripping

Type stripping is the biggest quality-of-life change in the 22 line. Node.js removes type annotations by replacing them with whitespace, then runs the result as JavaScript. According to the Node.js TypeScript documentation, it was added in 22.6.0, enabled by default in 22.18.0 without the experimental warning, and marked stable in 24.12.0.

# Node.js 22.18.0 or newer
node scripts/seed-database.ts

It is deliberately limited. Node does not type check, ignores tsconfig.json at runtime, and refuses syntax that needs code generation:

  • Not supported: enum, namespaces with runtime code, parameter properties and import aliases.
  • File rules: .tsx is unsupported, file extensions are mandatory in imports, and tsconfig paths are not resolved.
  • Type imports: use import type, or the import is treated as a runtime value and fails.
  • No node_modules: Node will not strip types from TypeScript files inside dependencies.

The docs recommend TypeScript 5.8 or newer with these options, so the compiler flags anything Node cannot run:

{
  "compilerOptions": {
    "noEmit": true,
    "target": "esnext",
    "module": "nodenext",
    "rewriteRelativeImportExtensions": true,
    "erasableSyntaxOnly": true,
    "verbatimModuleSyntax": true
  }
}

Keep running tsc --noEmit in CI, because type stripping skips checking entirely. My TypeScript strict mode guide covers the type checking side.

Type stripping replaces your TypeScript runner for scripts and tooling, not your type checker. Node runs the code; tsc still proves it is correct.

How require(esm) ends the ESM and CommonJS headache

For years, a CommonJS project could not require() a package that shipped only ES modules, which forced awkward dynamic imports or pinned old package versions. Node.js 22 fixed this. The modules documentation shows require(esm) was added in 22.0.0 behind a flag, enabled without the flag in 22.12.0, and stopped emitting an experimental warning by default in 22.13.0.

// CommonJS file, Node.js 22.12.0 or newer
const { formatPrice } = require('./money.mjs')

console.log(formatPrice(4990, 'AUD'))

One rule remains: the ES module graph must be synchronous. If the module or any of its imports uses top-level await, require() throws and you need import() instead. For library authors, this means shipping ESM only is now far less painful for CommonJS users on supported Node versions.

Is the built-in test runner ready to replace Jest?

For backend code, utilities and libraries, usually yes. The node:test module has been stable since Node.js 20, and the 22 line added several missing pieces: snapshot testing and module mocking arrived in 22.3.0, and coverage thresholds such as --test-coverage-lines arrived in 22.8.0.

Dense JavaScript code on a dark screen, the kind a built-in test runner checks
The built-in runner removes a dependency for most backend projects. Photo: rawpixel, CC0
// test/cart.test.ts
import { describe, it, mock } from 'node:test'
import assert from 'node:assert/strict'
import { cartTotal } from '../src/cart.ts'

describe('cartTotal', () => {
  it('sums line items in cents', () => {
    assert.equal(cartTotal([{ price: 1000, qty: 2 }, { price: 500, qty: 1 }]), 2500)
  })

  it('calls the tax service once', async () => {
    const getRate = mock.fn(async () => 0.1)
    await cartTotal([{ price: 1000, qty: 1 }], { getRate })
    assert.equal(getRate.mock.callCount(), 1)
  })
})
node --test --experimental-test-coverage --test-coverage-lines=80 "test/**/*.test.ts"

Some features are still flagged on Node.js 22: coverage needs --experimental-test-coverage, and mock.module() needs --experimental-test-module-mocks. For React component tests, browser-like environments or large existing Jest suites, Vitest remains the more practical choice.

Built-in WebSocket client and other web-standard APIs

Node.js 22 enabled the browser-compatible WebSocket global by default, and 22.4.0 removed its experimental status. The same code now works in the browser, in Node and in edge runtimes, without the ws package for client connections.

const ws = new WebSocket('wss://realtime.example.com/orders')

ws.addEventListener('open', () => ws.send(JSON.stringify({ subscribe: 'orders' })))
ws.addEventListener('message', (event) => {
  const update = JSON.parse(event.data)
  console.log('Order updated:', update.id)
})
ws.addEventListener('close', () => console.log('Disconnected'))

Combined with global fetch, AbortSignal and Web Streams, this keeps closing the gap between Node and browser APIs. That portability is what makes moving code between Node servers and platforms like Cloudflare Workers realistic, as I describe in my Cloudflare Workers guide. Note that the global is a client only; you still need a library to run a WebSocket server.

Small Node.js 22 features that save real time

These smaller Node.js 22 features each remove a dependency or a workaround:

  • node --run: runs package.json scripts with less overhead than npm run. It intentionally skips pre and post scripts, so check before switching.
  • Stable watch mode: node --watch server.ts restarts on file changes and was marked stable in 22.0.0, replacing nodemon for most setups.
  • fs.glob and globSync: added in 22.0.0 and marked stable in 22.17.0, so simple file matching no longer needs a glob package.
  • node:sqlite: a built-in SQLite module added in 22.5.0 and unflagged in 22.13.0. It is still experimental on Node 22, so use it for scripts, caches and tests rather than critical production data.
  • --env-file: loads .env files natively and lost its experimental label in 22.21.0.
  • Faster streams: the default high water mark rose from 16 KiB to 64 KiB, trading slightly more memory for throughput.
import { glob } from 'node:fs/promises'
import { DatabaseSync } from 'node:sqlite'

const db = new DatabaseSync('content-index.db')
db.exec('CREATE TABLE IF NOT EXISTS files (path TEXT PRIMARY KEY)')

const insert = db.prepare('INSERT OR IGNORE INTO files (path) VALUES (?)')
for await (const file of glob('content/**/*.md')) insert.run(file)

What did V8 12.4 and Maglev change for performance?

Node.js 22 ships V8 12.4. The Node.js 22 release announcement lists WebAssembly garbage collection, Array.fromAsync, new Set methods and iterator helpers as new language features, and enables V8's Maglev compiler by default on supported architectures. The Node team notes that Maglev improves performance for short-lived CLI programs, which covers build scripts and serverless functions.

Gains depend heavily on the workload, so benchmark your own app rather than trusting generic percentages. Run your load tests on the old and new versions, compare latency at the 95th and 99th percentiles plus memory, and only then roll out. Node.js 24 and 26 ship newer V8 versions again, so the same advice applies to those upgrades.

Should you stay on Node.js 22 or upgrade to 24 or 26?

Node.js 22 is safe for production until April 2027, but new projects should start on a newer line. My rule of thumb:

Whiteboard plan with weekly columns and sticky notes for scheduling a runtime upgrade
Plan the next upgrade before Node.js 22 reaches end of life. Photo: rawpixel, CC0
  1. New projects: start on Node.js 26 once it is LTS on October 28, 2026, or on Node.js 24 if a dependency or host lags behind.
  2. Existing Node.js 22 apps: schedule the upgrade to 24 or 26 for the first half of 2027, well before end of life.
  3. Before upgrading: check native add-ons, your hosting platform's supported versions and any deprecation warnings in your logs.
  4. Test it properly: run the full test suite and a load test, deploy to staging, then roll out gradually.

Frameworks are moving too. Next.js 16, for example, requires at least Node.js 20.9, and Node.js 20 is already end of life, so many teams are upgrading Node and their framework together. I walk through that combined upgrade in my Next.js App Router migration guide.

Frequently asked questions

Is Node.js 22 still supported?

Yes. Node.js 22 is in Maintenance LTS, which means it receives critical bug fixes and security updates until its end of life on April 30, 2027. It no longer gets new features. Existing production apps are fine on it for now, but you should plan an upgrade to Node.js 24 or 26 before that date.

Can Node.js 22 run TypeScript without a build step?

Yes, from version 22.18.0, which enabled type stripping by default. Node removes type annotations and runs the code, but it does not type check and does not support enums, runtime namespaces or parameter properties. It is ideal for scripts, tooling and tests. Production apps often still compile with a bundler or tsc.

Should I replace Jest with the Node.js test runner?

For backend services, utilities and libraries, it is worth trying. The built-in runner is stable, needs no dependencies and supports mocking, snapshots and coverage. Keep Jest or Vitest for React component tests, browser-like environments or large existing suites where migrating would cost more than it saves.

Which Node.js version should I use for a new project in 2026?

Use an LTS line. From October 28, 2026, Node.js 26 is the newest LTS and supported until April 2029, so it is the best default for new projects. Choose Node.js 24 if your hosting platform or a key dependency does not support 26 yet. Avoid starting new work on Node.js 22.

Make the most of Node.js 22 and plan your next upgrade

The best Node.js 22 features, type stripping, require(esm), the mature test runner, the WebSocket client, fs.glob and node --run, remove whole categories of tooling from a typical project. Adopt them on Node.js 22.18 or newer, keep type checking in CI, and put your move to Node.js 24 or 26 on the calendar before April 2027.

If you want help modernizing a Node.js backend or upgrading a production app safely, reach out through my contact form. You can see examples of my work in my case studies.

Related reading