env.dev

Bun vs Deno vs Node.js: Which Runtime in 2026?

Compare Bun 1.3, Deno 2.7, and Node.js 24 LTS. Benchmarks for cold start, throughput, and install speed; how each handles .env files; and when to pick which.

Last updated:

Three JavaScript runtimes, three philosophies, one decision. Node.js (v24 LTS, Krypton, Oct 2025) is the ecosystem default — every npm package, every cloud provider, every framework targets it first. Bun 1.3 (April 2026, MIT-licensed but Anthropic-acquired Dec 2025) is a Zig-based all-in-one toolchain that ships a runtime, package manager, bundler, and test runner in a single binary, optimized for raw throughput. Deno 2.7 (Feb 2026) is the security-first runtime from Node's original creator, with sandboxed permissions, native TypeScript, and the stable Temporal API. Pick one wrong and you spend a quarter migrating; pick one right and you delete a third of your devDependencies.

Pick Bun

For raw speed and DX

Greenfield apps, monorepos with slow installs, edge functions where cold start matters, teams who want zero-config TypeScript and a built-in test runner. Auto-loads .env with no flag.

Pick Deno

For security & TS-first

Code that runs untrusted input, edge platforms (Deno Deploy, Netlify Edge), one-off scripts, and organizations that have been bitten by supply-chain attacks. Sandboxed by default — no surprise file or network access.

Pick Node

For the safe boring choice

Production systems where boring is a feature, projects that depend on native addons, AWS Lambda non-edge, and any team where "we picked an alternative runtime" would be a headline in the postmortem. v24 LTS is supported until April 2028.

Bun vs Deno vs Node at a glance

 Bun 1.3Deno 2.7Node.js 24 LTS
ReleasedSep 2023 (1.0)May 2018 (1.0)May 2009 (0.0.1)
JS engineJavaScriptCore (WebKit)V8V8
Built inZigRustC++
LicenseMITMITMIT
Backed byAnthropic (Dec 2025)Deno Land Inc.OpenJS Foundation
Default permissionsOpenSandboxedOpen (opt-in --permission)
Native TypeScriptYesYesType-stripping only
Auto-loads .envYes--env-file required--env-file required

How fast is each runtime, really?

Synthetic "Hello World" benchmarks make Bun look like it lapped the field. Production benchmarks, where a request actually hits a database, mostly converge. Three numbers worth knowing in 2026:

AWS Lambda cold start (ms, lower is better)

Three-month production case study, equivalent handler. Bun reported 290ms vs Node's 940ms — a 69% improvement. No directly comparable Deno number was published in the same study; Deno Deploy is the Deno-native edge target. Source: Strapi, Bun vs Node.js benchmarks (2026).

Bun 1.3
290 ms
Node 24
940 ms

HTTP throughput on the same Express-style handler (k requests/sec, higher is better)

Single process, no database, identical handler code on each runtime. Bun's native Bun.serve reaches ~68k req/s on the same test. Real apps with database round-trips converge to roughly 12k req/s on all three. Source: DEV Community three-way benchmark (2026); ByteIota production-grade comparison (2026).

Bun
52k req/s
Deno
29k req/s
Node.js
14k req/s

Cold install of a 1,847-dependency monorepo (lower is better)

Empty cache, no lockfile reuse. Bun finishes in 47 seconds where npm takes 28 minutes — roughly 35× faster than npm and 5× faster than pnpm. deno install reads package.json as of 2.0; no directly comparable benchmark of deno install at this scale was published. Source: DEV Community (2026); Strapi (2026).

bun install
47s
pnpm install
4 min
npm install
28 min

The honest read: Bun wins package install and cold start by margins large enough to feel in CI and in Lambda-style serverless. It wins synthetic HTTP throughput by 2–4×. But Strapi's production-grade URL shortener — routing, validation, database — measured Bun at 12,400 req/s versus Node's 12,000, a < 3% gap that disappears into noise. ByteIota independently reports all three converging at roughly 12k req/s once a database is in the request path. Deno lands between the two on HTTP — ahead of Node, behind Bun — while winning on TypeScript transpile cost (it transpiles natively, no tsc step).

How do Bun, Deno, and Node handle .env files?

This is the one place env.dev cares about most, and it's also where the three runtimes diverge most sharply. See the .env guide for full syntax rules; the runtime differences are below.

Bun — auto-load

bash
# Just create .env
bun run server.ts

Bun reads .env, .env.local, and .env.{NODE_ENV} automatically. Values land on process.env, Bun.env, and import.meta.env. No flag, no dependency.

Deno — explicit

bash
deno run \
  --allow-env \
  --env-file=.env \
  server.ts

Deno requires both --env-file to load and --allow-env to read. Access via Deno.env.get("PORT"). No env access without explicit permission — the security model is the point.

Node — flag, no dep

bash
node \
  --env-file=.env \
  server.js

Stable since Node 24.10 (originally landed in v20.6, Aug 2023). No more dotenv dependency for the basic case. --env-file-if-exists skips missing files silently.

Gotcha: Node's --env-file is read before the permission model initializes, so .env bypasses --allow-fs-read. Deno's --env-file respects sandboxing. Bun has no permission model at all in 2026 — open by default, like Node without the --permission flag. If your threat model includes a malicious npm dependency reading .env, Deno is the only one of the three that defends by default.

For Node-side specifics — the string-everything trap, NODE_ENV=production side effects, cross-platform pitfalls — see Node.js environment variables. For the parser-level rules every runtime quietly disagrees on (multi-line values, comments, quoting), see .env file syntax.

Feature parity matrix

CapabilityBun 1.3Deno 2.7Node 24
Run TypeScript without compile stepNativeNativeStrip-only
npm registry compatibilityFullFull + JSRNative
CommonJS (require) supportYesVia npm:Native
ESM as defaultYesYesYes
Built-in test runnerbun test (Jest API)deno testnode --test
Built-in package managerbun installdeno installnpm
Built-in bundlerbun builddeno bundle (legacy)No
Watch modebun --watch--watch--watch
Permission sandboxNoneDefault-onOpt-in --permission
Web standard fetch / Request / ResponseYesYesYes
Stable Temporal APIBehind flag2.7 stableV8 14.5+
Native SQL client (Postgres / SQLite)Bun.SQL, bun:sqlitenode:sqlite via shimnode:sqlite (stable)
Compile to single binarybun build --compiledeno compile--experimental-sea-config

Who uses each in production?

Adoption signals matter more than benchmarks because they tell you what survives a year of operational pain.

Bun

  • Anthropic — uses Bun as core infra for Claude Code; led to the December 2025 acquisition.
  • DigitalOcean App Platform — native Bun runtime support shipped 2025.
  • Vercel & Cloudflare — both run Bun-built bundles in production edge environments.

Deno

  • Slack — runs customer code in their automation platform on Deno; chose it specifically for the secure-by-default sandbox.
  • The Guardian — audits accessibility and performance across 2.7M articles; Deno cited for TypeScript and security model.
  • Plaid — migrated 100 services 5× faster with Deno tooling.
  • Netlify Edge Functions — Deno-powered runtime.

Node.js

  • Nearly everyone else — Netflix, LinkedIn, PayPal, Walmart, Uber, NASA. The default JavaScript runtime since 2009.
  • AWS Lambda, Google Cloud Functions, Azure Functions — first-class Node support; Bun and Deno are still custom-runtime layers.
  • Every CI/CD pipeline — every action runner, every Dockerfile node:24-alpine base image.

What changed since the 2024 hype cycle?

Each runtime addressed its biggest 2024 weakness. The differences that mattered then mostly don't anymore.

  • Node 20.6 (Aug 2023) shipped --env-file, killing the most common reason to install dotenv. Node 24 LTS made the permission model stable as --permission, a feature Deno had had since day one.
  • Deno 2.0 (Oct 2024) reversed the early-Deno bet against npm and shipped first-class package.json support. Deno 2.7 (Feb 2026) added npm: overrides, JSR specifiers in package.json, and the stable Temporal API. The "you have to rewrite for Deno" objection is gone.
  • Bun 1.2 (Jan 2025) swapped its binary lockfile for the text-based bun.lock, fixing the diff-review problem that blocked production adoption. Bun 1.3 (Oct 2025) added Postgres via Bun.SQL, a Redis client, and zero-config frontend. Anthropic acquired the project in December 2025; the runtime is still MIT and open source, but now has corporate backing.
  • All three converged on web standards — global fetch, Request, Response, URLPattern, Web Crypto, and the WinterCG minimum surface. Code that uses standard APIs runs on all three with no changes.

How do you migrate from Node to Bun or Deno?

Both are designed as drop-ins, with caveats. The bigger your app's exposure to native addons (sharp, node-canvas, native bcrypt, custom NAPI modules), the more friction.

Node → Bun

bash
# 1. Install (curl one-liner or npm i -g bun)
curl -fsSL https://bun.sh/install | bash

# 2. Migrate lockfile
bun install
# Reads existing package-lock.json or pnpm-lock.yaml,
# writes bun.lock.

# 3. Run
bun run server.ts  # replaces `node` and `tsx`
bun test           # replaces jest/vitest in many cases

Watch out for: native modules (most work, some don't); Worker threads (different shape); process.binding and other private APIs.

Node → Deno

bash
# 1. Install
curl -fsSL https://deno.land/install.sh | sh

# 2. Use existing package.json or migrate
deno install   # reads package.json

# 3. Run with explicit permissions
deno run \
  --allow-net \
  --allow-env \
  --allow-read \
  --env-file=.env \
  server.ts

Watch out for: --allow-* flags everywhere until you tighten them; some packages need npm: prefix; Deno-specific globals (Deno.env) must be added if you want to use the security model fully.

Which is best for serverless / edge?

Cold start dominates this answer. Bun cold-starts at ~290ms in the AWS Lambda case study above, versus Node's ~940ms — a 3.2× gap that translates to lower p99 latencies for low-traffic functions. Deno is the runtime behind Netlify Edge Functions and Deno Deploy, where its instant-start design is the entire product. Node is still the default on Lambda, Cloud Functions, and Azure Functions; Bun and Deno require custom runtime layers on AWS as of May 2026.

The Cloudflare Workers angle is different: Workers run on V8 isolates, not Node, so the question becomes "does my code use Node-only APIs?" — increasingly answered by the nodejs_compat compatibility flag. env.dev itself runs on a Cloudflare Worker.

When should you stay on Node?

Boring is a feature. Pick Node when:

  • You depend on native addons that haven't been ported (some image processing, hardware drivers, legacy NAPI).
  • Your CI/CD, container base images, and IaC modules are all standardized on node: — switching costs more than it saves.
  • Your team has on-call rotation and "we picked an alternative runtime" would be the second sentence of every postmortem.
  • You ship libraries that need to work for the broadest install base — Node is the lowest-common-denominator target.
  • You're already happy with npm/pnpm, tsx/ts-node, and vitest; the all-in-one toolchain pitch isn't worth the migration to you.

Key takeaways

  • Bun wins on raw throughput, install speed, and zero-config DX — and it auto-loads .env.
  • Deno wins on security (sandboxed by default), TypeScript ergonomics, and edge runtime story.
  • Node wins on ecosystem, tooling, hiring, cloud platform support, and "nobody got fired for picking Node."
  • The runtimes have converged on web standards — code using fetch/Request/Response ports across all three with minor friction.
  • For .env: Bun auto-loads, Deno requires --env-file + --allow-env, Node requires --env-file only. None auto-load on a bare invocation except Bun.
  • Real-world HTTP throughput gaps narrow to < 5% once a database is in the request path; the synthetic 3× advantage rarely survives production.

Sources

Was this helpful?

Frequently Asked Questions

Is Bun faster than Node.js?

Yes for synthetic benchmarks. Strapi's 2026 measurements show Bun at ~52k requests/sec versus Node's ~13k on the same Express handler, and a 290ms vs 940ms AWS Lambda cold start in a three-month production case study (69% faster). Once a database is in the request path the gap collapses — Strapi's URL-shortener test measured Bun at 12,400 req/s and Node at 12,000, under 3% difference.

Should I use Deno or Node.js in 2026?

Use Deno if security matters — it is sandboxed by default, requires explicit --allow-net and --allow-env, and is the only mainstream runtime that defends against malicious npm packages reading your .env. Use Node if you depend on native addons, ship libraries, or run on AWS Lambda / Cloud Functions where Node has first-class support.

Does Bun auto-load .env files?

Yes. Bun reads .env, .env.local, and .env.{NODE_ENV} automatically with no flag and no dependency. Values are exposed on process.env, Bun.env, and import.meta.env. Node requires --env-file (stable in v24.10), Deno requires --env-file plus --allow-env.

Can I migrate from Node to Bun without rewriting my app?

Mostly. Bun reads existing package.json, package-lock.json, and pnpm-lock.yaml; bun install writes bun.lock. The friction points are native addons (most work via NAPI, some do not), Worker threads, and private process.binding APIs. Pure JavaScript / TypeScript apps usually run unchanged.

Who uses Deno in production?

Slack runs customer code on Deno in their automation platform, citing the secure-by-default sandbox. The Guardian audits 2.7M articles for accessibility and performance with Deno. Plaid migrated 100 services 5× faster with Deno tooling. Netlify Edge Functions runs on Deno. Deno had 107k GitHub stars as of early 2026.

What did Deno 2.7 add over earlier versions?

Deno 2.7 (Feb 2026) stabilized the Temporal API, added Windows on ARM builds, npm overrides in package.json, JSR specifiers in package.json, --save-exact for pinned installs, self-extracting compiled binaries, brotli compression streams, and dozens of node:* compatibility fixes. The "Deno cannot use npm packages" objection from 2023 is gone.