Unico Connect
Node.js development guide for 2026, LTS versions, native TypeScript and the permission model
Back to Blog
EngineeringAugust 25, 202612 min read

Node.js Development Guide for 2026

Anurag Kurmi

Anurag Kurmi

Senior Full Stack Engineer, Unico Connect

In this article

Node.js is the most used web technology in the industry. The Stack Overflow Developer Survey 2025, with 23,678 respondents, puts it at 48.7 percent usage, ahead of React at 44.7 percent. That popularity hides how much the runtime itself has changed in the last two years. Node now runs TypeScript files without a build step, ships a stable permission model that can lock a process out of the file system, and, most urgently, the version a great many production services are still running went out of support in April 2026.

This guide covers the four decisions that actually matter in Node.js development this year. Which version to run, how far the native TypeScript support goes, whether the permission model is worth adopting, and where Node is the wrong tool.

Quick Answer

Run Node.js 24, the Krypton line, for new and upgraded production services. It has been Active LTS since 28 October 2025 and carries security support until 30 April 2028. Node 20 reached end of life on 30 April 2026 and receives no further security patches, so anything still on it needs upgrading now. Node 22 is safe through 30 April 2027 but is already in maintenance. Node runs TypeScript directly since version 22.18.0 with no flag, but it only strips types and never checks them, so you still need the TypeScript compiler in continuous integration. The permission model reached stable in v22.13.0 and v23.5.0 and is genuinely useful, with documented gaps worth reading before you rely on it.

Key Takeaways

  • Node 24 is the current Active LTS and the correct default for production in 2026, with security support until 30 April 2028.
  • Node 20 hit end of life on 30 April 2026. There are no more security patches for that line, which makes it the single most common piece of unmanaged risk in Node estates right now.
  • Native TypeScript is real but narrow. Type stripping is on by default from v22.18.0, and it ignores tsconfig.json, performs no type checking, and rejects any TypeScript syntax that would need code generation.
  • Parameter properties are unsupported by type stripping, which is why a NestJS application still needs a real build step rather than running straight from source.
  • The permission model is stable, not experimental. It can restrict file system, network, child process, and worker access, with real caveats around worker threads, symbolic links, and existing file descriptors.

Which Node.js Version to Run

Node.js release lines in August 2026, support windows and what to do with each

Node.js release lines in August 2026, support windows and what to do with each
Release lineStatus in August 2026Security support untilWhat to do
Node 26Current, becomes Active LTS on 28 October 202630 April 2029Test against it now, hold production until it reaches LTS
Node 24, KryptonActive LTS since 28 October 202530 April 2028The default choice for new services and upgrades
Node 22, JodMaintenance since 21 October 202530 April 2027Safe for now, plan the move to Node 24 this year
Node 20End of life since 30 April 2026Support has endedUpgrade now, no further security patches will be issued
Node 25End of life since 1 June 2026Support has endedOdd numbered line, never LTS, move to Node 24

Dates from the official Node.js release schedule published by the Node.js project.

Dates come from the official Node.js release schedule. The pattern is worth internalising. An even numbered line becomes Active LTS in the October after its release, spends a year as Active LTS, then moves to maintenance for another eighteen months. Odd numbered lines never become LTS and should never carry production traffic.

Node 20 Is End of Life, and That Matters More Than It Sounds

Node 20 stopped receiving support on 30 April 2026. In practice that means any vulnerability found in the runtime from May 2026 onward will not be patched for that line. There is no partial support and no grace period.

The upgrade from 20 to 24 is usually undramatic. Both are modern V8 releases, and most breakage comes from native modules that need rebuilding rather than from application code. A workable sequence is this.

Step one, pin and inventory. Establish which services are on which line. A dependency audit that reports the runtime version per deployed service is more useful here than a package audit.

Step two, rebuild native dependencies. Anything with a compiled component, such as database drivers, image processing, or cryptography bindings, needs reinstalling against the new ABI rather than copying node_modules forward.

Step three, run the test suite on 24 in continuous integration before changing production. Add the new version alongside the old one in the matrix rather than replacing it, so you can see both results.

Step four, move one low traffic service first and watch memory and event loop lag for a week before rolling the rest.

Native TypeScript, What Works and What Does Not

Since v22.18.0 you can hand a TypeScript file straight to Node with no flag and no build step.

node server.ts

On v22.0 through v22.17 the same thing needs an explicit flag.

node --experimental-strip-types server.ts

What Node does here is type stripping, through a loader called Amaro. It removes the type annotations and runs the resulting JavaScript. It does not compile in the fuller sense, and three consequences catch teams out.

Node does not type check. Nothing about running a file through Node validates your types. A file with a genuine type error runs happily until it fails at runtime. Type checking stays a separate step.

npx tsc --noEmit

Node ignores tsconfig.json. The Amaro loader does not read your project configuration, so path aliases, target settings, and strictness options have no effect on what Node executes. Your editor and the compiler still read tsconfig, which means local tooling and the runtime can disagree.

Syntax that needs code generation is rejected. Anything that has to emit JavaScript rather than simply delete characters is unsupported. That covers enums, parameter properties, namespaces with runtime behaviour, and import aliases that are not type only.

// Runs. Pure annotations, erasable.
interface User {
  id: string
  email: string
}
type Role = 'admin' | 'viewer'
const owner: User = { id: 'u_1', email: 'a@b.com' }

// Fails under type stripping. Both need generated code.
enum Status {
  Active,
  Suspended,
}
class UserService {
  constructor(private readonly db: Database) {}
}

That last example is the practical catch. Parameter properties, the shorthand where a constructor argument is also a class field, are how NestJS dependency injection is normally written. So a NestJS codebase cannot run directly from source under type stripping and still needs a build step. Express and Fastify services written in plain annotated TypeScript usually can.

Our recommendation is to use native stripping for scripts, tooling, and small services where the build step is pure overhead, and to keep a real compiler in the pipeline for structured applications. In both cases run tsc --noEmit in continuous integration, because the runtime will never do it for you. TypeScript 5.7 or newer is the matching compiler baseline.

The Permission Model Is Stable and Almost Nobody Uses It

The Node.js permission model stopped being experimental in v22.13.0 and v23.5.0. It lets you start a process with an explicit allowance and deny everything else, which is a meaningful reduction in blast radius for a runtime whose dependency trees are as deep as this one.

node --permission \
  --allow-fs-read=/app \
  --allow-fs-write=/app/tmp \
  --allow-net \
  server.js

There is also an audit mode, which reports what a process would have been denied without actually blocking it. That is the sane way to introduce this to an existing service.

node --permission-audit server.js

The available allowances cover file system reads and writes, network access, child processes, worker threads, native addons, WASI, and foreign function interface calls. The value is obvious for anything that runs third party code, evaluates user supplied logic, or executes AI generated code paths.

Now the caveats, which the official documentation lists and which you should read before depending on this.

  • Worker threads do not inherit the permissions of the parent, so a restricted process can spawn a less restricted worker.
  • Symbolic links are followed even when they point outside a granted path.
  • File descriptors that already exist can be used through node:fs to bypass the model.
  • Process signalling is not gated, so process._debugProcess can force inspector access on another process.
  • OpenSSL engines and SQLite loadable extensions cannot be used while the model is enabled.
  • Flags that read files before the model initialises, such as --env-file, are not subject to it.

Read that list as a boundary rather than a disqualification. The permission model is a strong additional layer and a poor sole defence.

Production Patterns That Hold Up

Four things separate a Node service that ages well from one that becomes a rescue project, and none of them are new or version specific.

Never block the event loop. Node handles concurrency on a single thread per process, so a synchronous CPU heavy operation stalls every other request in flight. Move that work to a worker thread, a separate service, or a queue. Slow endpoints under load are usually this, not the database.

One process is not a scaling plan. A single Node process uses one core. Run multiple instances behind a load balancer, or a container per core under an orchestrator, and make sure the process is genuinely stateless before you do.

Shut down gracefully. Handle the termination signal, stop accepting new connections, let in flight requests finish, close database pools, then exit. Without this every deployment drops requests, which shows up as mysterious intermittent errors that correlate with releases.

Log structured and log the request. JSON logs with a correlation identifier per request are the difference between diagnosing a production problem in minutes and guessing for an afternoon.

When Node.js Is the Wrong Choice

Node is excellent at input and output bound work, which is most web software. It is a poor fit for sustained CPU bound computation, such as video transcoding, large numerical workloads, or model training, where Python, Go, or Rust will serve you better. It is also the wrong default when your team has deep expertise elsewhere and the product has no real time or high concurrency requirement, because runtime choice matters less than the fluency of the people using it.

For the fuller language comparison, including where Python and Java win, see our guide to Node vs Python vs Java.

How Unico Connect Builds Node.js Services

We build Node.js backends in strict TypeScript with NestJS for structured platforms and Express or Fastify for lighter and high throughput services, with automated tests and continuous integration from the first commit. Every pull request gets senior engineer review, services deploy into cloud accounts you own, and you keep the code and the intellectual property throughout, under our ISO/IEC 27001:2022 and ISO 9001:2015 certified practice. Rates run 25 to 50 dollars per hour depending on seniority and focused builds start from 15,000 dollars.

See our Node.js development service for the full practice, or hire Node.js developers to add backend capacity to a team you already have. For the infrastructure side of the same work, see cloud and DevOps.

The most common Node problem I am asked to look at is not a framework choice. It is a service on an unsupported runtime, with no type checking in the pipeline, that blocks the event loop under load. All three are cheap to fix and none of them require a rewrite. Upgrade the runtime, add one continuous integration step, and move the heavy work off the request path.

Anurag Kurmi, Senior Full Stack Engineer, Unico Connect

Where These Numbers Come From

Every release date, support window, and status in this guide comes from the official Node.js release schedule published by the Node.js project. The native TypeScript behaviour, including the version at which type stripping became the default and the list of unsupported syntax, comes from the Node.js documentation on running TypeScript natively. The permission model status, flags, and limitations come from the Node.js permissions API documentation. The 48.7 percent usage figure comes from the Stack Overflow Developer Survey 2025, which had 23,678 respondents. Our own rate band and project floor are Unico Connect list ranges rather than market averages.

Frequently Asked Questions

Which Node.js version should I use in 2026?

Node 24, the Krypton line, for anything going to production. It became Active LTS on 28 October 2025 and has security support until 30 April 2028. Node 22 remains supported until 30 April 2027 but is in maintenance, so it receives fixes rather than improvements. Node 26 becomes Active LTS on 28 October 2026 and is worth testing against before then, not deploying.

Is Node 20 still supported?

No. Node 20 reached end of life on 30 April 2026 and receives no further security patches. If you are running it in production, treat the upgrade as a security task rather than a maintenance one. The move to Node 24 is usually straightforward, with native module rebuilds being the most common source of friction.

Can Node.js run TypeScript natively?

Yes, since version 22.18.0, with no flag required. Node strips the type annotations and runs the JavaScript underneath. On versions 22.0 through 22.17 you need the experimental strip types flag. This works well for scripts and straightforward services.

Does Node.js type check my TypeScript?

No, and this is the most misunderstood part of the feature. Node removes types without validating them, so code with real type errors will run until it fails at runtime. Keep the TypeScript compiler in your pipeline and run it in check only mode. Node also ignores tsconfig.json entirely, so your compiler settings do not influence what the runtime executes.

Why will my NestJS application not run with node app.ts?

Because NestJS relies on parameter properties for dependency injection, and parameter properties require generated code rather than simple type removal. Type stripping rejects that syntax, so a NestJS project still needs a genuine build step. Express and Fastify services written with plain type annotations usually run directly.

Is the Node.js permission model production ready?

It is stable rather than experimental, having reached that status in v22.13.0 and v23.5.0, and it is a sensible additional layer. It is not a complete sandbox. Worker threads do not inherit restrictions, symbolic links are followed outside granted paths, and existing file descriptors can bypass it. Start in audit mode, understand what your service actually touches, then enforce.

Is Node.js good for real time applications?

Yes, that is one of its strongest cases. The event driven model handles large numbers of concurrent open connections efficiently, which suits chat, live dashboards, collaborative editing, and streaming. The caveat is the same as everywhere else in Node, namely that any CPU heavy work on the request path will stall the whole process.

Conclusion

Node.js development in 2026 comes down to unglamorous discipline rather than framework fashion. Run a supported line, which means Node 24 for most teams and an urgent upgrade if you are still on 20. Use native TypeScript where it genuinely removes a build step, and never mistake it for type checking. Adopt the permission model in audit mode and understand its gaps before you rely on it. Keep CPU work off the request path.

To choose between runtimes rather than versions, read Node vs Python vs Java. To have this built or reviewed by our team, see Node.js development, hire Node.js developers, or contact us.

Keep reading

Latest Blogs & Articles

View all