Node.js Development Guide for 2026

Anurag Kurmi
Senior Full Stack Engineer, Unico Connect
In this article
- Quick Answer
- Key Takeaways
- Which Node.js Version to Run
- Node 20 Is End of Life, and That Matters More Than It Sounds
- Native TypeScript, What Works and What Does Not
- The Permission Model Is Stable and Almost Nobody Uses It
- Production Patterns That Hold Up
- When Node.js Is the Wrong Choice
- How Unico Connect Builds Node.js Services
- Where These Numbers Come From
- Frequently Asked Questions
- Conclusion
Node.js is the most used web technology among surveyed developers. The Stack Overflow Developer Survey 2025 puts it at 48.7 percent usage among the 23,678 respondents to its web frameworks and technologies question, 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.
Four decisions carry most of the weight in Node.js development this year, namely 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. Since version 22.18.0 Node runs TypeScript directly with no flag. 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 useful, though its documented gaps are worth reading before you rely on it. At Unico Connect we recommend native stripping for scripts, tooling, and small services where the build step is pure overhead, and a real compiler in the pipeline for structured applications.
Key Takeaways
- Put new and upgraded production services on Node 24. It is the current Active LTS and the correct default for production in 2026, with security support until 30 April 2028.
- Treat any service still on Node 20 as open security exposure. The line hit end of life on 30 April 2026 and gets no more security patches, which makes it the single most common piece of unmanaged risk in Node estates right now.
- Keep the TypeScript compiler in continuous integration even when Node runs your files directly. Type stripping is on by default from v22.18.0, but it ignores tsconfig.json, performs no type checking, and rejects any TypeScript syntax that would need code generation.
- NestJS projects still need a real build step. Type stripping supports neither decorators nor parameter properties, and NestJS dependency injection is normally written with both, so a NestJS application cannot run straight from source.
- The permission model is stable and can restrict file system, child process, and worker access, with real caveats around worker threads, symbolic links, and existing file descriptors, so on Node 24.20.0 or later switch it on in audit mode first.
Which Node.js Version to Run
Node.js release lines in August 2026, support windows and what to do with each
| Release line | Status in August 2026 | Security support until | What to do |
|---|---|---|---|
| Node 26 | Current, becomes Active LTS on 28 October 2026 | 30 April 2029 | Test against it now, hold production until it reaches LTS |
| Node 24, Krypton | Active LTS since 28 October 2025 | 30 April 2028 | The default choice for new services and upgrades |
| Node 22, Jod | Maintenance since 21 October 2025 | 30 April 2027 | Safe for now, plan the move to Node 24 this year |
| Node 20 | End of life since 30 April 2026 | Support has ended | Upgrade now, no further security patches will be issued |
| Node 25 | End of life since 1 June 2026 | Support has ended | Odd 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, and the pattern behind them is worth learning. 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. Any vulnerability found in the runtime from May 2026 onward stays unpatched on that line, with 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 has four steps.
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 to the matrix next to the old one and keep both, so you can compare the results side by side.
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.6 through v22.17 the same thing needs an explicit flag.
node --experimental-strip-types server.ts
Node does this through type stripping, using a loader called Amaro. It removes the type annotations and runs the JavaScript left behind. Nothing is compiled in the fuller sense, and three consequences catch teams out.
Node does not type check. Running a file through Node validates nothing about your types, so a file with a real 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. Type stripping can only delete characters, so any syntax that has to emit JavaScript 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) {}
}
The class in that last example is the one that bites in practice. Parameter properties, the shorthand where a constructor argument is also a class field, are how NestJS dependency injection is normally written. NestJS also marks its services, controllers, and modules with decorators, and the Node.js TypeScript documentation says decorators are not transformed and cause a parser error. 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 advice splits by project type. Use native stripping for scripts, tooling, and small services where the build step is pure overhead, and 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.8 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 meaningfully shrinks the blast radius, given how deep Node dependency trees run.
node --permission \
--allow-fs-read=/app \
--allow-fs-write=/app/tmp \
server.js
Since v24.20.0 and v25.8.0 there is also an audit mode, which reports what a process would have been denied without blocking it. That makes it the sane way to bring the model into an existing service.
node --permission-audit server.js
The available allowances cover file system reads and writes, child processes, worker threads, native addons, and WASI. Network access gained an allowance in v25.0.0 and foreign function interface calls in v26.1.0, so add --allow-net to the example above only on Node 25 or later. The value is obvious for anything that runs third party code, evaluates user supplied logic, or executes AI generated code paths.
The official documentation lists the caveats, and you should read them before depending on the model.
- A worker thread keeps the parent permission flags by default, but an explicit
execArgvreplaces them, so a restricted process with--allow-workercan 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:fsto bypass the model. - Process signalling is not gated, so
process._debugProcesscan 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.
Those gaps mark where the model stops protecting you, and they do not rule it out. It makes 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 usually come down to this, so check it before you blame the database.
A single Node process uses one core, so scaling means running more of them. Put multiple instances behind a load balancer, or run a container per core under an orchestrator, and make sure the process is stateless before you do.
Every service also needs a graceful shutdown. Handle the termination signal, stop accepting new connections, let in flight requests finish, close database pools, then exit. Skip it and every deployment drops requests, which shows up as odd intermittent errors that line up with releases.
Finally, log structured JSON with a correlation identifier on every request. With that in place a production problem takes minutes to diagnose, and without it you can spend an afternoon guessing.
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.
Our Node vs Python vs Java comparison works through the language choice in full, including where Python and Java win.
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 10,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, cross checked against the previous releases table. 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, where 23,678 respondents answered the web frameworks and technologies question. 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 now gets fixes and no new improvements. Node 26 becomes Active LTS on 28 October 2026. Test against it before then and hold production deploys until that date.
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, and native module rebuilds are 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.6 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?
NestJS relies on decorators and on parameter properties for dependency injection, and type stripping supports neither. Decorators are not transformed and cause a parser error, and parameter properties need generated code that type removal cannot produce, so a NestJS project still needs a proper build step. Express and Fastify services written with plain type annotations usually run directly.
Is the Node.js permission model production ready?
Yes, as a sensible additional layer. It moved from experimental to stable in v22.13.0 and v23.5.0. It is still not a complete sandbox, since a worker thread started with its own flags can drop the restrictions, symbolic links are followed outside granted paths, and existing file descriptors can bypass it. On Node 24.20.0 or later, start in audit mode, learn what your service 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 more than framework fashion. Run a supported line, which for most teams means Node 24, and upgrade urgently if you are still on 20. Use native TypeScript where it removes a build step, and never mistake it for type checking. Adopt the permission model in audit mode and learn its gaps before you rely on it. Keep CPU work off the request path.
If you are still choosing the runtime itself, 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.




