Deno vs Node.js vs Bun
Compare the three JavaScript runtimes by runtime model, permissions, TypeScript, package management, tooling, and deployment to make a selection decision
This is a decision-by-dimension comparison, not a benchmark chart. All three runtimes evolve quickly: compatibility claims, default behavior, and performance conclusions can change between releases. This page only states what was verified against official sources on the date above.
Dimension-by-dimension comparison
| Dimension | Deno 2 | Node.js | Bun |
|---|---|---|---|
| Engine and model | V8 + Rust; Web API first, URL imports, Deno.serve | V8 + libuv; node: built-ins, the ecosystem's reference point | JavaScriptCore + Zig; implements both Web APIs and Node APIs |
| Permission model | Deny by default; --allow-* scoped by host, path, and env var | Full access by default; optional --permission model (added in v20, no longer experimental since v23.5/v22.13), documented as a "seat belt," not a security boundary | Full access by default; this page could not verify an equivalent built-in permission model in official docs — check current Bun docs before deciding |
| TypeScript | Runs natively with full type checking via built-in deno check | Type stripping on by default (since v23.6/v22.18, marked stable in v25.2/v24.12); erasable syntax only, no type checking, no .tsx | Transpiles and runs TS directly; type checking is delegated to tsc (the official recommended tsconfig sets noEmit) |
| Package management and registries | Native package.json, node_modules, and npm workspaces; npm: and jsr: specifiers; deno add/install/ci | npm registry and package.json are the ecosystem baseline; pnpm/yarn via Corepack or the package manager's own installer (Corepack no longer ships with Node as of Node 25) | Compatible with package.json/node_modules; bun install is the built-in package manager |
| Toolchain | fmt, lint, check, test, bench, doc, and compile built in | node:test and --watch built in; formatting and linting come from the ecosystem | test, bunx, bundler, and single-file compilation built in |
| Node compatibility status | node:/npm: specifiers plus package.json support; details evolve, verify with real tests | The reference itself | Officially targets Node compatibility with a per-module status table: "If a package works in Node.js but doesn't work in Bun, we consider it a bug" |
| Ecosystem and hiring | Smaller ecosystem; npm compatibility lowers switching cost | Largest package ecosystem, hosting support, and hiring pool | Smaller ecosystem; npm compatibility lowers switching cost |
| Deployment shapes | Containers/VMs/serverless + Deno Deploy + deno compile single-file binaries | Containers/VMs/serverless with the broadest hosting support | Containers/VMs + bun build --compile single-file binaries |
Performance: do not quote other people's benchmarks
This page lists no numbers. Public benchmarks are highly sensitive to hardware, versions, and workload shape, and vendor-published numbers usually pick favorable scenarios. Measure your own workload instead:
- Pin runtime and dependency versions (record
deno --version,node --version,bun --versionin the report). - Run on the same machine and dataset; capture startup time, steady-state throughput, p50/p99 latency, and resident memory.
- Separate microbenchmarks (JSON serialization, Hello World) from real paths (framework middleware, database drivers, TLS). The former rarely predicts the latter.
- Measure startup-sensitive scenarios (CLIs, cold starts) separately from long-running services.
- Archive results together with versions, OS/arch, and commands; rerun after upgrades before comparing.
When to choose which
| Constraint | Leaning |
|---|---|
| Maintaining an existing Node production system; hiring, training, and hosting support matter most | Node.js |
| New project; TypeScript first; zero-config fmt/lint/test/compile; deny-by-default permission sandbox required | Deno |
| Publishing a TypeScript library for both Deno and Node consumers | Deno + JSR |
| Install and startup speed is critical, and you are willing to validate npm compatibility with real tests | Bun |
| Existing Node project, evaluating or migrating to Deno incrementally | Start with Migrating from Node.js |
There is no universal answer. Treat the table as an elimination tool: first remove options that fail hard constraints (permissions, hosting, existing code, team experience), then benchmark what remains against your own workload.
Official sources: Deno 2.0 release notes, Deno Node compatibility docs, Node.js TypeScript support, Node.js permission model, Bun Node.js compatibility table, Bun TypeScript docs.