Deno spent its first four years being "Node but secure" — an interesting experiment that most teams watched from a distance. Deno 2.0, released in late 2024, changed that calculus by landing full npm compatibility, a stable standard library, and performance that benchmarks ahead of Node in several I/O-heavy workloads. In 2026, the choice is no longer obvious.
What changed in 2026
- Deno 2.0 ships npm compatibility by default —
npm: specifiers work for the overwhelming majority of the npm registry, ending the "missing package" blocker.
- JSR (JavaScript Registry) became the preferred module host for new Deno packages, with TypeScript-native publishing and automatic
.d.ts generation.
- Node 22 became LTS with the stable
--watch mode, improved fetch support, and the experimental permissions model (--experimental-permission).
- Bun 1.x matured as a third contender — faster cold starts than both, but less mature stability for production servers.
- Edge runtimes (Deno Deploy, Cloudflare Workers) converged on the WinterCG API surface, reducing lock-in concerns.
Core differences
| Factor |
Deno 2.0 |
Node 22 LTS |
| TypeScript support |
Built-in, zero config |
Via ts-node / tsx / tsc |
| npm packages |
Full (npm: specifier) |
Native |
| Module system |
ESM + CJS compat |
ESM + CJS |
| Standard library |
Stable (JSR) |
Node built-ins + npm |
| Permissions sandbox |
Yes (opt-in) |
Experimental |
| Built-in formatter |
deno fmt |
Requires Prettier |
| Built-in linter |
deno lint |
Requires ESLint |
| Built-in test runner |
deno test |
node --test (stable 2024) |
| Cold start |
Fast (~30 ms) |
Moderate (~60–80 ms) |
| Ecosystem size |
Growing (JSR + npm) |
2.5 M+ packages |
| Hosting support |
Deno Deploy + most clouds |
Universal |
When Deno makes sense
- New TypeScript projects where you want zero-config TS without a build step.
- Edge functions on Deno Deploy — the global deploy model is first-class.
- Scripting and CLI tools — built-in formatter, linter, and test runner remove the setup tax.
- Security-sensitive environments — explicit permission flags (
--allow-net, --allow-read) make the surface area auditable.
// deno.json — no tsconfig, no package.json, no node_modules
{
"tasks": {
"dev": "deno run --watch --allow-net main.ts"
},
"imports": {
"@std/http": "jsr:@std/http@^1.0",
"zod": "npm:zod@^3.23"
}
}
// main.ts — TypeScript, no compilation step
import { serve } from "@std/http";
import { z } from "zod";
serve((req) => new Response("Hello from Deno 2026"), { port: 8000 });
When Node makes sense
- Existing codebase — there is no practical reason to migrate a working Node app.
- Obscure npm packages — the majority of the registry works in Deno, but native addons (
.node binaries) do not.
- Framework-heavy stacks — NestJS, Fastify, and Express are deeply Node-native; Deno compatibility is good but not perfect.
- Team familiarity — Node has broader hiring availability and more community Q&A.
node_modules tooling you rely on — monorepo setups, module mocking in Jest, and complex build pipelines are well-understood in Node.
// Node 22 — native TypeScript support via --experimental-strip-types
// (no ts-node needed for simple scripts)
node --experimental-strip-types server.ts
How to pick
- Greenfield TypeScript project? → Try Deno; zero-config TS is genuinely pleasant.
- Existing Node codebase? → Stay on Node; migration cost is real.
- Deploying to Cloudflare Workers or Deno Deploy? → Deno or the WinterCG-compatible subset either way.
- Need native addons or obscure npm packages? → Node.
- Want Bun-level startup speed? → Evaluate Bun as a third option before committing.
Common mistakes
Assuming Deno is dramatically faster than Node. In most real web server benchmarks the difference is 5–15%. Profile your actual bottleneck; the runtime is rarely it.
Using deno.land/x packages in 2026. The old deno.land/x registry is deprecated in favor of JSR. New projects should use JSR imports.
Forgetting permission flags in scripts. A Deno script that needs network access will throw at runtime without --allow-net. Build permissions into your task runners from the start.
Choosing Node "because it is safer." Node 22's experimental permission model is functional but not the primary reason to choose Node. Make the choice on ecosystem and team fit, not security theater.
What to skip
- ts-node in new Node projects —
tsx or Node's own --experimental-strip-types are faster and better maintained.
- CommonJS (
require) in new code — both runtimes support ESM; write ESM from day one.
- Rewriting Node scripts in Deno for the sandbox — add a linter and strict module boundaries instead; the security ROI of a full rewrite is usually negative.
FAQ
Can Deno run Express apps?
Yes, via npm compatibility. npm:express works. But Hono or @std/http are better fits for Deno's model.
Is Deno ready for production?
Yes — Deno Deploy runs production workloads for thousands of apps. The caution is around native addons and unusual npm packages, not stability.
What about Bun in 2026?
Bun is faster on startup and SQLite, but its Node compatibility has more edge cases. Teams that need maximum throughput for new projects benchmark all three.
Does Node get a built-in TypeScript compiler?
Node 22+ supports --experimental-strip-types for simple TS scripts. Full compilation for complex projects still goes through tsc or esbuild.
Where to go next