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

DimensionDeno 2Node.jsBun
Engine and modelV8 + Rust; Web API first, URL imports, Deno.serveV8 + libuv; node: built-ins, the ecosystem's reference pointJavaScriptCore + Zig; implements both Web APIs and Node APIs
Permission modelDeny by default; --allow-* scoped by host, path, and env varFull 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 boundaryFull access by default; this page could not verify an equivalent built-in permission model in official docs — check current Bun docs before deciding
TypeScriptRuns natively with full type checking via built-in deno checkType stripping on by default (since v23.6/v22.18, marked stable in v25.2/v24.12); erasable syntax only, no type checking, no .tsxTranspiles and runs TS directly; type checking is delegated to tsc (the official recommended tsconfig sets noEmit)
Package management and registriesNative package.json, node_modules, and npm workspaces; npm: and jsr: specifiers; deno add/install/cinpm 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
Toolchainfmt, lint, check, test, bench, doc, and compile built innode:test and --watch built in; formatting and linting come from the ecosystemtest, bunx, bundler, and single-file compilation built in
Node compatibility statusnode:/npm: specifiers plus package.json support; details evolve, verify with real testsThe reference itselfOfficially 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 hiringSmaller ecosystem; npm compatibility lowers switching costLargest package ecosystem, hosting support, and hiring poolSmaller ecosystem; npm compatibility lowers switching cost
Deployment shapesContainers/VMs/serverless + Deno Deploy + deno compile single-file binariesContainers/VMs/serverless with the broadest hosting supportContainers/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:

  1. Pin runtime and dependency versions (record deno --version, node --version, bun --version in the report).
  2. Run on the same machine and dataset; capture startup time, steady-state throughput, p50/p99 latency, and resident memory.
  3. Separate microbenchmarks (JSON serialization, Hello World) from real paths (framework middleware, database drivers, TLS). The former rarely predicts the latter.
  4. Measure startup-sensitive scenarios (CLIs, cold starts) separately from long-running services.
  5. Archive results together with versions, OS/arch, and commands; rerun after upgrades before comparing.

When to choose which

ConstraintLeaning
Maintaining an existing Node production system; hiring, training, and hosting support matter mostNode.js
New project; TypeScript first; zero-config fmt/lint/test/compile; deny-by-default permission sandbox requiredDeno
Publishing a TypeScript library for both Deno and Node consumersDeno + JSR
Install and startup speed is critical, and you are willing to validate npm compatibility with real testsBun
Existing Node project, evaluating or migrating to Deno incrementallyStart 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.

Type to search all documentation.