Node vs Bun vs Deno in 2026: The Self-Hosting Verdict

For self-hosting real apps in 2026, pick Node.js 24 LTS for stable long-running processes, Bun 1.3 for install speed, and Deno 2.8 for single-binary deploys. On my own box, Bun installs an 847-package monorepo in 1.2 seconds versus npm’s 32, but Node still wins the 3am stability test.

Key Takeaways

  • Node.js 24 LTS stays the safest default for long-running production processes.
  • Bun installs dependencies 20 to 40 times faster than npm in real projects.
  • Deno compiles to a single 28MB binary, the simplest self-host deploy there is.
  • Node now ships a test runner, watch mode, and TypeScript, closing the gap.
  • Native C/C++ addons work in Node and Bun but not in Deno.

Three runtimes now fight for the same job: running your server-side JavaScript. Node.js is the 16-year incumbent. Bun bets on raw speed. Deno bets on security and a single binary. This post compares them for one specific use: self-hosting a real app on hardware you own, not a synthetic hello-world race.

Here are the current builds. Node.js 24 is the active LTS line, with Node.js 24 becoming LTS and version 26 now the Current branch. Bun shipped v1.3.14 . Deno tagged its 2.8 release . All three move fast. So check your own lockfile before you trust a number from any blog.

Which JavaScript Runtime Is Fastest in 2026?

Speed splits into three numbers that really differ here: startup, HTTP throughput, and install time. Bun leads on all three in raw tests. However, the lead shrinks fast once a real database and middleware enter the picture.

Startup time is where Bun looks strongest. Bun boots in roughly 8 to 15ms, Deno in 40 to 60ms, and Node.js in 60 to 120ms, figures that line up with Strapi’s Bun versus Node guide . On a real cold Lambda, Bun averaged about 290ms against Node’s 940ms in a three-month production case study . For serverless, that gap is real money.

Bar chart comparing AWS Lambda cold-start times for Bun, Deno, and Node.js across a three-month production benchmark
AWS Lambda cold-start benchmarks across runtimes
Image: Deno

HTTP throughput tells a similar story on paper. In a hello-world test, Bun handled about 52,000 requests per second. Node managed 13,000. With a fast framework like Hono , byteiota’s 2026 runtime benchmarks put Bun near 110,000, Deno near 85,000, and Node near 45,000.

Benchmark chart comparing JavaScript runtime performance across Bun, Node.js, and Deno in 2026
2026 JavaScript runtime performance comparison
Image: byteiota

Here is the honest part, though. In head-to-head benchmarks under realistic load with a database, JSON, and middleware, the gap collapses to roughly 12,400 versus 12,000 requests per second. As byteiota notes, real benchmarks mislead : your bottleneck is almost always the database, not the runtime.

Install speed is the one number where Bun’s lead survives reality. On an 847-package monorepo, bun install runs in about 1.2 seconds versus npm’s 32 . For a medium project, daily.dev’s comparison clocks Bun near 1 second, Deno near 17, and npm near 20.

Why the split? Bun uses JavaScriptCore plus a binary lockfile and zero-copy cloning. Node and Deno both run V8, so their raw speed sits closer than the hype suggests. The big Bun wins are startup and install, not steady request handling.

RuntimeLatest versionStartup / HTTP req/snpm compatibilityBuilt-in TS / test / bundlerLTS
Node.js 24 LTS24 (26.3 Current)60-120ms, ~13k-45kNative, 100%TS stripping + node:test, no bundlerFormal LTS to Apr 2028
Bun 1.3.141.3.148-15ms, ~52k-110kVery high (JSC)TS + bun:test + bun buildNo formal LTS
Deno 2.8.22.8.240-60ms, ~85k76% Node compatTS + deno test + deno bundleNo formal LTS

How Compatible Are Bun and Deno With npm and the Node API?

Compatibility is the biggest blocker to switching, so this is where most moves live or die. Node.js is the baseline. All of the npm ecosystem and every node: module work there. The real question is how close Bun and Deno get.

Deno has closed most of the gap. Deno 2.8 understands package.json, node_modules, and npm workspaces out of the box, as the Deno Node compatibility docs lay out. Its Node API compatibility jumped to 76.4% with Deno 2.8 , and the Deno 2.8 release notes confirm the CLI no longer needs the npm: prefix. For a Node project, Deno now feels less foreign than it used to.

As of Deno 2.8, over 75% of Node’s own test suite passes in Deno, covering nearly every node: module.

Deno team (Deno blog, 2026)

Bun aims higher: near-total Node support through JavaScriptCore. Bun 1.2 was its biggest compat release yet. It improved Windows and node:cluster support. Most packages just work, but edge cases remain, as Bun’s Node compatibility docs admit. Before you bet a production app on it, read what actually works in Bun in 2026 .

The practical effect is simple. Deno gives you a published compat number you can check against your deps. Bun gives you “probably fine, test the weird stuff.” Neither one replaces a real test run on your own package tree.

Does the All-in-One Toolchain Still Beat Node in 2026?

The first pitch for Bun and Deno was “batteries included.” Node, by contrast, needed a dozen dev dependencies. That pitch was strong in 2023. Node has since caught up, which changes the math.

Node.js 24 now ships the headline features itself. It has a stable built-in test runner (node:test) and a native --watch mode. It also strips TypeScript types by default for erasable syntax, per the Node.js TypeScript docs . For many teams, that erases the reason they reached for Bun or Deno in the first place.

There is a catch with Node’s TypeScript, though. It only strips erasable syntax. It does no type checking, and it ignores tsconfig.json on purpose. So you get no path aliases and no decorators by default, as the Node.js type-stripping docs spell out. You still need tsc for real type safety.

Node also still lacks two things on its own: a production bundler and a formatter. Bun answers with bun build plus built-in SQLite, Postgres, and S3 clients in one binary. Deno answers with deno fmt, deno lint, secure-by-default permissions, and deno compile.

So the verdict depends on why you want to switch. Maybe you only wanted to drop ts-node, nodemon, and a Jest config. If so, Node 24 has likely closed that gap. If you want a bundler and a formatter with no extra installs, Bun and Deno still pull ahead.

Self-Hosting and Production Fit on Your Own Box

This is the angle most comparisons skip. When I self-host web apps on my own box, the deciding factor was never requests per second. It was whether docker compose up stays healthy for weeks without the container creeping up in memory.

On my own deployments, Node.js has been the boring, reliable default. I reach for Bun where install speed in CI is the bottleneck. I keep a close eye on memory before trusting it with a process that has to live for days. That instinct is backed by real numbers below.

Docker image size counts for more than people expect on a small box. The numbers, per the Node Docker variants guide and the 2026 runtime battle writeup , favor the slim builds:

  • node:24-alpine: about 55MB
  • oven/bun: about 84 to 89MB
  • deno: about 73MB
  • full node:24: about 389MB

Single-binary compile is where Deno gets interesting for self-hosting. Both deno compile and bun build --compile produce one self-contained file. Deno’s binary averages about 28MB, per the Deno compile-npm announcement . There is no node_modules to ship and no runtime to install on the host. Node has no first-class match.

# Deno: produces a ~28MB standalone binary, no runtime needed on the host
deno compile --allow-net --output server main.ts

# Bun: same idea, single executable
bun build --compile ./index.ts --outfile server

Native addons draw a hard line. Node is the reference for the N-API. Bun builds in Node-API, so most prebuilt .node addons load as-is. Deno dropped native plugins for FFI and does not support Node-API . So an app that needs such an addon simply will not run there. Check your dependency tree for .node files before you pick Deno.

Long-running stability is where Node’s lead holds. V8’s garbage collector is the proven choice for 72-hour-plus processes. Bun saw real memory-leak reports and a 1.1.13 fix in April 2026 . Some tests show Bun using 50 to 75% more RAM. Others show it 25 to 40% leaner. Treat Bun’s long-haul memory as “verify on your own workload.”

Migration cost from Node rounds out the picture. It is lowest for Deno inside an existing Node project, since Deno reads package.json and node_modules. Bun is mostly drop-in. Still, you must regression-test native addons and rare node: APIs. The lowest-risk path many teams land on is Bun in dev, Node in production .

RuntimeDocker (alpine/slim)Cold startSingle-binaryNative addonsMemory under loadMigration from Node
Node.js~55MB (389MB full)~940msNo first-class compileFull native supportProven, stableNone (baseline)
Bun~84-89MB~290msYes (bun build –compile)Works via Node-API, test edgesFaster but leak reportsLow, drop-in with caveats
Deno~73MB (28MB compiled)40-60msYes (deno compile, ~28MB)No Node-API (FFI/WASM only)Stable, V8-basedLow if no native addons

A Fair Hello-World in All Three

To frame the speed numbers honestly, here is the same HTTP server in each runtime. The code is nearly identical, which is the point. The runtime, not the syntax, drives the difference.

// Node.js 24 (node:http)
import { createServer } from "node:http";
createServer((req, res) => res.end("hello")).listen(3000);

// Bun (built-in serve)
Bun.serve({ port: 3000, fetch: () => new Response("hello") });

// Deno (built-in serve)
Deno.serve({ port: 3000 }, () => new Response("hello"));

One note on scope. This covers server-side self-hosting, not browser bundling or edge-only Workers runtimes like Cloudflare Workers and workerd . Those are siblings with different trade-offs. If you do not want to switch runtimes at all, pnpm gives you a fast, npm-compatible installer on plain Node.

Which JavaScript Runtime Should You Choose?

Each runtime now owns a clear lane. The trick is matching the lane to your actual deployment, not to a benchmark leaderboard.

Decision tree mapping native addon and LTS needs to Node.js 24, install speed to Bun 1.3, and single-binary deploys to Deno 2.8

Choose Node.js 24 LTS for long-running services, anything that leans on native addons, and teams that want a multi-year support window. It ships a formal LTS schedule through April 2028 . It is the default you have to be talked out of, not into.

Choose Bun 1.3 for fast CI installs, serverless cold-start savings, greenfield apps, and a snappy dev loop. Just verify long-running memory before you trust it with multi-day processes.

Choose Deno 2.8 for secure-by-default scripts and CLI tools, single-binary deploys, and TypeScript-first projects that value built-in fmt and lint. It shines when you do not need V8 native addons.

RuntimeBest forAvoid if
Node.jsProduction stability, native addons, enterprise LTSYou want the absolute fastest install and cold start
BunCI install speed, serverless cold starts, greenfieldMulti-day processes where memory must not drift
DenoSingle-binary deploys, secure scripting, TS-firstYou depend on V8 native addons

The real reframe for 2026 is this. The question is less “which runtime” and more “do Node’s new built-in tools already give me 80% of the all-in-one win at zero migration risk?” For many self-hosters, the honest answer is yes.