Engineering • 12 min read
TypeScript vs Deno vs Bun (2026): Performance, Features, and When to Use Each
If you're building scalable web applications, choosing the right runtime is crucial. Let's look at TypeScript vs Deno vs Bun to see which modern JavaScript ecosystem actually delivers. This isn't just about syntactical quirks — we're doing a deep dive into real-world performance, native capabilities, and overall latency. In this comprehensive comparison, we'll analyze the trade-offs of each platform in 2026 so you know exactly which tool to adopt.
TypeScript 6.0 just dropped in March 2026. It's the last release built on JavaScript. The next one is being rewritten in Go. Deno 2.7 shipped in February with Temporal API support, Windows ARM builds, and full npm compatibility. Bun 1.3 is now the runtime powering Anthropic's Claude Code after being acquired earlier this year.
All three shipped major updates within months of each other. All three are being used in production right now. And all three make different trade-offs that matter depending on what you're building.
This article covers performance benchmarks, developer experience, security, ecosystem compatibility, and real-world use cases. We're not declaring a winner. There isn't one. The right answer depends on your team, your codebase, and what you're actually trying to ship.
The only honest answer to "which should I use?" is: it depends. But we'll tell you exactly what it depends on.
Quick Comparison Table
Before we go deep, here's the high-level view. Use this to orient yourself, then read the details below.
| Feature | TypeScript 6.0 | Deno 2.7 | Bun 1.3 |
|---|---|---|---|
| What it is | Type-checking compiler | Runtime + toolchain | Runtime + toolchain |
| Engine | N/A (compiles to JS) | V8 | JavaScriptCore |
| Written in | JavaScript (TS 7.0 in Go) | Rust | Zig |
| Latest version | 6.0 (Mar 23, 2026) | 2.7 (Feb 25, 2026) | 1.3.11 |
| TypeScript support | Native, full type-checking | Built-in, zero config | Transpilation only, no type-checking |
| Package manager | Uses npm/yarn/pnpm | Built-in (deno install) |
Built-in (bun install) |
| Bundler | No (needs external) | Built-in | Built-in |
| Test runner | No (needs external) | Built-in (deno test) |
Built-in (bun test) |
| Security model | None (compile-time only) | Permissions-first | Node.js-compatible (unrestricted) |
| Node.js compat | Full (runs on Node) | High (npm: specifiers) | Near-complete (drop-in) |
| Cold start speed | N/A (needs runtime) | Moderate | Fastest |
| Binary size | N/A | ~122MB (Linux, LTO) | ~100MB |
| Edge deployment | Via runtime choice | Deno Deploy (GA) | Vercel (native) |
| Acquired by | Microsoft (owns) | Independent | Anthropic |
What Each Tool Actually Is (And What It Isn't)
TypeScript 6.0: The Type System That Became Infrastructure
TypeScript isn't a runtime. Let's get that out of the way first. It's a type-checking layer that compiles to JavaScript. You still need something to actually run your code — Node, Deno, Bun, whatever.
So why include it in a runtime comparison? Because TypeScript 6.0 changes the game. Strict mode now defaults to true. ESM is the default module system. And this is the last release on the JavaScript codebase. TypeScript 7.0 is being rewritten in Go — Project Corsa — promising 10x speedup, native compilation, and shared-memory parallelism.
Current version: 6.0, released March 23, 2026. Backed by Microsoft, Anders Hejlsberg, and the largest JS/TS ecosystem on earth. If you're writing JavaScript at any scale, you're probably already using TypeScript. The question isn't whether to adopt it. It's what runtime you run it on.
Deno 2.7: The Secure-by-Default Runtime That Finally Got Node Compatibility Right
Deno was created by Ryan Dahl — the same person who created Node.js — specifically to fix Node's mistakes. That's not marketing copy. That's the origin story. Built on V8, written in Rust, ships as a single binary.
Security is built in from day one. No implicit file or network access. Everything requires explicit permissions. That's the core design philosophy, and it hasn't changed.
Current version: 2.7, released February 25, 2026. Temporal API is stabilized. Windows ARM builds exist now. npm overrides in package.json work. Deno Deploy went GA in February 2026 — production-ready edge hosting. Deno Sandbox lets you run untrusted code in secure Linux microVMs.
The big shift over the last year: Deno finally got npm compatibility right. You can use npm: specifiers to pull packages directly. No more "Deno doesn't work with my existing code" excuses.
Bun 1.3: The Speed Demon Now Powering Anthropic's AI Tools
Bun is built on JavaScriptCore — the engine that powers Safari — not V8. It's written in Zig. It's fast. Not "kind of fast." Actually fast.
It's also all-in-one: runtime, package manager, bundler, test runner. You install one thing and get everything. That's the pitch, and it mostly delivers.
Current version: 1.3.x, latest is 1.3.11. TC39 standard ES decorators. Windows ARM64 support. Native REPL. And the big news: Bun has been acquired by Anthropic. It will power Claude Code, Claude Agent SDK, and future AI coding products. Vercel now supports Bun runtime natively with full API access.
Bun 1.3 highlights include Bun.cron for OS-level cron jobs, Bun.sliceAnsi for ANSI-aware string slicing, and 500x faster postMessage(string) for inter-thread communication.
Bun is no longer just a runtime. It's AI infrastructure. That changes the calculus.
Architecture Comparison
Understanding what's under the hood matters more than most comparisons admit.
| Layer | TypeScript 6.0 | Deno 2.7 | Bun 1.3 |
|---|---|---|---|
| JS Engine | N/A | V8 13.4 | JavaScriptCore (upgraded) |
| Language | JavaScript | Rust | Zig |
| Module System | ESM + CommonJS | ESM (native), CommonJS via npm: | ESM + CommonJS |
| Type Checking | Full (tsc) | Built-in (TS 5.7) | None (transpilation only) |
| Threading | Single-threaded (Worker threads via runtime) | Web Workers, Web Workers | Worker threads, postMessage (500x faster) |
| Compilation | Ahead-of-time (tsc) | JIT (V8) + deno compile (AOT) |
JIT (JSC) + bun build --compile (AOT) |
| Standard Library | None | Extensive (std/) |
Built-in APIs (Bun.*) |
| Next Version | 7.0 (Go rewrite) | 3.0 (speculated) | Post-Anthropic (unknown) |
Performance: The Numbers That Actually Matter
Startup Time and Cold Boots
Bun starts faster than both Node and Deno on most workloads. That's JavaScriptCore's advantage — it's lighter than V8 out of the gate. For CLI tools, test suites, and serverless cold starts, this matters.
Deno's V8 startup is heavier. But deno compile produces standalone binaries that close the gap significantly. Once compiled, Deno doesn't need to re-parse and re-JIT on every run.
TypeScript adds a compilation step before anything runs. Zero runtime cost, but you pay upfront. In watch mode, it's manageable. In CI, it adds time.
Here's a rough comparison for a simple console.log("hello") script:
| Tool | Cold Start (ms) | Notes |
|---|---|---|
| Bun | ~5-10ms | JavaScriptCore, minimal overhead |
| Deno (raw) | ~30-50ms | V8 startup, permission checks |
| Deno (compiled) | ~5-15ms | Pre-compiled binary, no JIT needed |
| Node + tsc | ~50-100ms | tsc compile + Node startup |
| Node + tsx | ~80-150ms | On-the-fly transpilation |
Bun wins raw startup. Deno's compile feature narrows it. TypeScript needs a runtime underneath — it doesn't compete here.
Package Installation Speed
This is where Bun shines. bun install uses a global lockfile cache, parallel installs, and native code. It's up to 30x faster than npm on large projects. That's not marketing — that's measurable.
Bun 1.2 introduced bun.lock — a text-based lockfile replacing the binary bun.lockb. Better diffs. Fewer merge conflicts. GitHub can actually render it now.
Deno's approach is different. Content-addressed cache. No node_modules. URL-based imports. It's fast, but the mental model is entirely different from npm. If you're coming from Node, it takes adjustment.
TypeScript adds @types/* installation overhead on top of whatever runtime you use. That's a tax everyone pays.
| Tool | Install Method | Speed vs npm | Lockfile |
|---|---|---|---|
| npm | npm install |
1x (baseline) | package-lock.json |
| pnpm | pnpm install |
~2-3x faster | pnpm-lock.yaml |
| Bun | bun install |
Up to 30x faster | bun.lock (text) |
| Deno | deno install / URL imports |
Varies (no node_modules) | Content-addressed cache |
Bun is fastest for npm projects. Deno's cache is smarter for long-term projects. npm is the baseline everyone compares against.
Runtime Execution Speed
V8 (Deno/Node) vs JavaScriptCore (Bun). The engine war continues.
JavaScriptCore wins on certain workloads — particularly short-lived processes and memory-constrained environments. V8 still dominates on complex, long-running code where JIT optimization maturity matters.
Bun 1.2 made Express 3x faster than Node.js through node:http compatibility improvements. Deno 2.7 made node:fs.cpSync 2x faster than Deno 2.1 and 3x faster than Node.js 20. Both are closing the gap.
TypeScript has zero runtime overhead. It compiles away completely. Your JavaScript runs at whatever speed your runtime gives it.
| Benchmark | Bun 1.3 | Deno 2.7 | Node.js 24 |
|---|---|---|---|
| Express req/sec | ~100k+ | ~60-70k | ~30-40k |
node:fs.cpSync |
Fast | 3x faster than Node 20 | Baseline |
| JSON parsing | Very fast | Fast (V8 optimized) | Fast |
| Crypto operations | Moderate | Fast (V8) | Fast |
| Short-lived scripts | Fastest | Moderate | Moderate |
| Long-running servers | Fast | Fastest (V8 JIT maturity) | Fast |
For short-lived processes: Bun. For long-running servers: V8 (Deno/Node) still holds up. TypeScript doesn't affect runtime speed.
Memory Usage
Bun's idle memory is lower than Node's — reduced by 10-30% in recent releases. JavaScriptCore is just lighter than V8 at rest.
Deno's memory profile is predictable. V8's baseline is heavier, but it's consistent. Deno 2.7 clears module analysis info after timeout, reducing memory consumption on long-running processes.
TypeScript's real memory hog isn't the compiler. It's the language server — tsserver — in large codebases. This is what developers actually feel when their IDE starts lagging. TypeScript 7.0 in Go should help here, but that's not out yet.
| Scenario | Bun 1.3 | Deno 2.7 | TypeScript LSP |
|---|---|---|---|
| Idle process | ~20-40MB | ~50-80MB | N/A |
| Large codebase LSP | N/A | ~200-400MB | ~500MB-1GB+ |
| HTTP server (idle) | ~30-50MB | ~60-100MB | N/A |
| Memory growth | Low, stable | Predictable | Depends on codebase size |
Bun uses less memory at idle. Deno is predictable. TypeScript's LSP is the real memory bottleneck in large projects.
Developer Experience: What It Actually Feels Like to Use These Tools
Setup and Onboarding
TypeScript: npm init, npm install -D typescript, tsc --init. Then the tsconfig.json rabbit hole begins. You'll spend an afternoon figuring out moduleResolution, baseUrl, paths, and why your imports still don't work. It gets better. But the first day is rough.
Deno: zero config. deno run file.ts just works. Permission prompts on first run for file and network access. You don't install anything except the Deno binary. That's it.
Bun: bun init. Drop-in Node replacement. Familiar if you know npm workflows. The learning curve is shallow because it's designed to feel like Node.
First 30 minutes with each tool: Deno is easiest. Bun is most familiar. TypeScript requires the most setup.
Here's what a "hello world" setup looks like for each:
# TypeScript 6.0 — the full ritual
mkdir my-app && cd my-app
npm init -y
npm install -D typescript
npx tsc --init
# Now edit tsconfig.json, add your source files, configure paths...
npx tsc
node dist/index.js
# Deno 2.7 — one command
deno run index.ts
# That's it. Permission prompts appear on first run.
# Bun 1.3 — familiar but fast
bun init
bun run index.ts
# Or just: bun index.ts
TypeScript Support (Yes, All Three Handle TypeScript)
TypeScript 6.0 is the native experience. Full type-checking. Strict mode now defaults to true. module defaults to esnext. target defaults to es2025. This is the gold standard for type safety.
Deno 2.7 has built-in TypeScript support. No transpilation step. deno run file.ts just works. It upgraded to TypeScript 5.7 under the hood. Workspace-scoped compilerOptions are now supported. JSDoc @import tags are respected in type checking. LSP auto-completion is 5-20x faster. It also supports .svelte, .vue, and .scss formatting out of the box.
Bun 1.3 has TypeScript transpilation built in. But no type-checking. You still need tsc or a separate type-checking step. Bun transpiles fast. It doesn't catch type errors. That's a meaningful distinction.
Here's how each handles a TypeScript file:
// app.ts
interface User {
name: string;
age: number;
}
function greet(user: User): string {
return `Hello, ${user.name}!`;
}
// This should error — missing required property
const result = greet({ name: "Alice" });
console.log(result);
| Tool | Command | Result |
|---|---|---|
| TypeScript 6.0 | npx tsc app.ts |
Error: Property 'age' is missing |
| Deno 2.7 | deno run app.ts |
Error: Type check fails, won't run |
| Bun 1.3 | bun run app.ts |
Runs anyway — transpiles but doesn't type-check |
| Bun + tsc | bun run app.ts && npx tsc --noEmit |
Error caught by tsc, but separate step |
Deno has the smoothest TS DX. TypeScript 6.0 has the best type-checking. Bun is fastest but shallow — it transpiles but doesn't type-check.
Breaking Changes in TypeScript 6.0 You Need to Know
If you're upgrading from TS 5.x, expect to fix your tsconfig. The new defaults are better but will break old projects.
strict is now true by default. Old projects will break. module defaults to esnext. target defaults to es2025. types defaults to [] (empty) — many projects need to add "types": ["node"] explicitly. rootDir now defaults to . instead of being inferred.
Deprecated: target: es5, --downlevelIteration, --moduleResolution node (node10), amd/umd/systemjs modules, --baseUrl, --outFile, --esModuleInterop false.
The dom lib now includes dom.iterable and dom.asynciterable — no more adding both. New types for Temporal API (stage 4), Map.getOrInsert / Map.getOrInsertComputed, RegExp.escape.
Here's a migration checklist:
// Before (TS 5.x tsconfig.json)
{
"compilerOptions": {
"strict": false,
"module": "commonjs",
"target": "es2020",
"moduleResolution": "node",
"baseUrl": "./src",
"esModuleInterop": false
}
}
// After (TS 6.0 — what you need to fix)
{
"compilerOptions": {
"strict": true, // Now default — will break old code
"module": "esnext", // Now default
"target": "es2025", // Now default
"types": ["node"], // Must add explicitly (was implicit)
"rootDir": "./src", // Was inferred, now defaults to "."
// REMOVED — these are deprecated:
// "baseUrl": "./src",
// "moduleResolution": "node",
// "esModuleInterop": false
}
}
If you're upgrading from TS 5.x, expect to fix your tsconfig. The new defaults are better but will break old projects.
Package Management
npm/yarn/pnpm ecosystem is TypeScript's home turf. Massive. Mature. Slow. And node_modules is still a mess.
Deno's approach: URL imports, npm specifiers (npm:package), JSR registry (jsr:@scope/package), no node_modules, content-addressed cache. It's cleaner. It's different. Your team will need to learn it.
Bun's approach: npm-compatible. bun.lock text lockfile (introduced in 1.2, default in 1.3). Workspace support. .npmrc support. bun publish. bun patch for modifying dependencies without forking. bun outdated. bun pm whoami. bun pm pack. CA certificate support. --omit=dev|optional|peer flags. bun install --linker=isolated for pnpm-style isolated node_modules. bun why for dependency tree understanding.
JSR (JavaScript Registry) is Deno's TypeScript-first, ESM-only registry. OpenAI, Supabase, Hono, Neon already published there. It's growing.
Here's how you install the same package across all three:
# npm (TypeScript's default)
npm install express
npm install -D @types/express
# Bun — same command, much faster
bun add express
# No @types needed for most packages — Bun handles it
# Deno — different model entirely
# Option 1: npm specifier in code
import express from "npm:express@4";
# Option 2: JSR registry (TypeScript-first)
deno add jsr:@std/http
# Option 3: URL import (Deno's original approach)
import { serve } from "https://deno.land/std@0.224.0/http/server.ts";
| Feature | npm/yarn/pnpm | Bun | Deno |
|---|---|---|---|
| Lockfile format | JSON/YAML | bun.lock (JSONC) |
Content-addressed cache |
node_modules |
Yes | Yes (or isolated with --linker=isolated) |
No |
| Private registries | Yes (.npmrc) |
Yes (.npmrc + CA certs) |
Yes (.npmrc discovery) |
| Patching deps | patch-package |
bun patch (built-in) |
Not directly |
| Publishing | npm publish |
bun publish |
deno publish (JSR) |
| Workspace support | Yes (npm/pnpm) | Yes | Yes |
| Speed | Baseline | Up to 30x faster | Fast (no node_modules) |
Bun gives you the fastest npm experience. Deno gives you a completely different (and cleaner) model. TypeScript works with both.
The Toolchain Question
TypeScript needs a runtime (Node, Deno, or Bun) + bundler (Vite, esbuild, webpack) + test runner (Jest, Vitest). That's the standard stack. It works. It's just not one thing.
Deno 2.7: runtime + package manager + formatter + linter (with plugin API) + test runner + bundler + bench tool — all built in. One binary. No npm install for your tooling.
Bun 1.3: runtime + package manager + bundler + test runner — all built in. Same philosophy as Deno, different implementation.
Deno 2.7's lint plugin API is ESLint-like. 15+ new JSX/React rules. CSS-like selectors for targeting nodes. deno audit for security scanning. deno task supports wildcards in task names, tasks without commands for grouping, and proper signal forwarding.
Bun 1.3's test runner supports JUnit XML output, LCOV coverage, inline snapshots, test.only(), custom error messages, jest.setTimeout() support, VS Code test integration, --grep flag, and fake timers with @testing-library/react.
| Capability | TypeScript (Node) | Deno 2.7 | Bun 1.3 |
|---|---|---|---|
| Runtime | Via Node/Deno/Bun | Built-in | Built-in |
| Package manager | npm/yarn/pnpm | Built-in | Built-in |
| Bundler | Vite/esbuild/webpack | Built-in (deno bundle) |
Built-in (bun build) |
| Test runner | Jest/Vitest | Built-in (deno test) |
Built-in (bun test) |
| Formatter | Prettier | Built-in (deno fmt) |
Built-in (bun fmt via plugins) |
| Linter | ESLint | Built-in (deno lint) + plugins |
Via external tools |
| Benchmark tool | External | Built-in (deno bench) |
External |
| Task runner | npm scripts | Built-in (deno task) |
bun run |
| Binary size | N/A | ~122MB | ~100MB |
Deno and Bun are all-in-one. TypeScript needs a runtime and a toolchain. That's not a weakness — it's a design choice that gives you flexibility.
Security: Who Actually Protects Your Code
TypeScript's Security Model
TypeScript provides zero runtime security. It's a compile-time tool. Type safety catches bugs before they run, but that's not security.
Supply chain considerations: npm packages are the attack surface, not TypeScript itself. The axios backdoor incident from March 2026 is a perfect example — the attack vector was npm, not the type system.
TS 6.0's new noUncheckedSideEffectImports (default true) catches typos in side-effect-only imports. It's a small but real security improvement. It won't stop a determined attacker. But it catches mistakes.
Deno's Security-First Design
Permissions model: --allow-read, --allow-net, --allow-env, --allow-run. Granular control down to specific paths and URLs. No implicit file system or network access. Code can't phone home without permission.
Deno 2.7 relaxed Deno.cwd() — it no longer requires full --allow-read permission. Small change, meaningful quality-of-life improvement.
Deno Sandbox: instant Linux microVMs for running untrusted code with defense-in-depth security. This is new in 2026 and it's significant. If you're running third-party code or user-submitted scripts, this matters.
Here's what Deno's security model looks like in practice:
# This will FAIL — no permissions granted
deno run server.ts
# error: Requires read access to "./data", run again with --allow-read
# This works — explicit permissions
deno run --allow-read=./data --allow-net=:3000 server.ts
# Granular: allow only specific URLs
deno run --allow-net=api.example.com,cdn.example.com server.ts
# Deno Sandbox — run untrusted code in a microVM
deno sandbox --allow-net=:3000 untrusted-script.ts
Compare that to Bun and Node, where the same code runs with full system access:
# Bun — runs with full system access by default
bun run server.ts
# No permission prompts. Full file system, network, and env access.
# Node — same thing
node server.ts
# No permission prompts. Full system access.
Deno is the only runtime designed with security as a first principle. If you're running untrusted code or handling sensitive data, this matters.
Bun's Security Posture
Bun inherits Node.js's security model: unfettered system access by default. If it works in Node, it works in Bun. That's the philosophy. Compatibility over restriction.
Supply chain: bun install speed vs security trade-offs. Faster installs mean less time auditing. That's not a criticism — it's a reality. Speed and security pull in opposite directions.
The Anthropic acquisition: will Bun get a security overhaul? Unknown. Right now, Bun trusts you to know what you're installing.
| Security Feature | TypeScript | Deno 2.7 | Bun 1.3 |
|---|---|---|---|
| Runtime permissions | None | Yes (granular) | None (Node-compatible) |
| Sandboxing | None | Deno Sandbox (microVMs) | None |
| Supply chain scanning | None | deno audit |
None |
| Side-effect import checks | noUncheckedSideEffectImports |
Built-in | None |
| Postinstall scripts | Runs by default (npm) | Requires --allow-run |
Runs by default |
| CA certificate support | Via runtime | Via runtime | Built-in in bun install |
Bun trusts you to know what you're installing. That's fine for internal tools. It's a risk for anything handling user data or running third-party code.
Ecosystem and Compatibility
Node.js Compatibility
TypeScript runs on Node.js. Full compatibility by design. The entire npm ecosystem is your playground.
Deno 2.7 has full npm compatibility. Can run most Node projects. node: built-in modules work. .npmrc discovery happens in home and project directories. npm overrides in package.json work. Brotli compression streams are native. Self-extracting compiled binaries exist now. deno create scaffolds projects.
Bun 1.3 has near-complete Node.js compatibility. Runs the Node.js test suite for every commit. Reports as Node.js v24.x. TC39 standard ES decorators work. Windows ARM64 support is here.
Deno 2.7 Node.js compatibility highlights: 17+ improvements, source phase imports, faster type checking with tsgo, deno audit for security scanning, DoS vulnerability mitigations for React Server Components.
Bun 1.3 Node.js compatibility: Bun.cron for OS-level cron jobs, dgram UDP fixes on macOS, fs.openSync numeric flags fixed on Windows, http2 WINDOW_UPDATE fixes, numerous Node.js compatibility improvements.
Here's how the same Node.js code runs across all three:
// server.js — standard Node.js HTTP server
const http = require("node:http");
const server = http.createServer((req, res) => {
res.writeHead(200, { "Content-Type": "text/plain" });
res.end("Hello from the server!\n");
});
server.listen(3000, () => {
console.log("Server running on http://localhost:3000");
});
| Runtime | Command | Works? | Notes |
|---|---|---|---|
| Node.js | node server.js |
Yes | Native |
| Deno 2.7 | deno run --allow-net=:3000 server.js |
Yes | Needs --allow-net |
| Bun 1.3 | bun run server.js |
Yes | Drop-in, no changes |
| TypeScript | npx tsc && node dist/server.js |
Yes | Needs compilation step |
The "can I just swap my runtime?" test: Bun passes most of the time. Deno passes most of the time. TypeScript runs on whatever runtime you choose.
Framework Support
Next.js, React, Vue, Svelte — all work on all three, but with different levels of friction.
Deno Deploy runs Next.js SSR on Deno's edge network. Fresh is Deno's own React-like framework. Deno Deploy went GA in February 2026 — it's production-ready now.
Bun on Vercel: native Bun runtime support. Deploy Bun functions directly with full Bun API access. No workarounds needed.
Deno 2.7 LSP improvements: better support for modern frameworks, wildcard module augmentation, deno lint plugin API for custom rules.
TypeScript is the universal type layer across all frameworks. React, Vue, Svelte, Angular — all have first-class TS support. That's not changing.
| Framework | TypeScript | Deno 2.7 | Bun 1.3 |
|---|---|---|---|
| Next.js | Full support (official) | Via Deno Deploy (SSR) | Native on Vercel |
| React | Full support | Works (Fresh framework) | Works |
| Vue | Full support | Works | Works |
| Svelte | Full support | Works (.svelte formatting) |
Works |
| Astro | Full support | Experimental | Works |
| Remix | Full support | Works | Works |
| Fresh (Deno's framework) | N/A | Native | Not supported |
| Hono | Full support | Native (JSR) | Works |
For framework work: TypeScript + your runtime of choice. For edge: Deno Deploy. For Vercel: Bun has native support.
Code Examples: Same Task, Three Tools
Let's build a simple HTTP API that reads from a database and returns JSON. Here's how each tool approaches it.
TypeScript 6.0 (on Node.js)
// src/server.ts
import http from "node:http";
import { Pool } from "pg";
const pool = new Pool({
connectionString: process.env.DATABASE_URL,
});
interface User {
id: number;
name: string;
email: string;
}
const server = http.createServer(async (req, res) => {
if (req.url === "/api/users" && req.method === "GET") {
try {
const { rows } = await pool.query<User>("SELECT * FROM users");
res.writeHead(200, { "Content-Type": "application/json" });
res.end(JSON.stringify(rows));
} catch (error) {
res.writeHead(500);
res.end(JSON.stringify({ error: "Internal server error" }));
}
} else {
res.writeHead(404);
res.end(JSON.stringify({ error: "Not found" }));
}
});
server.listen(3000, () => {
console.log("Server running on http://localhost:3000");
});
# Setup and run
npm install -D typescript @types/node @types/pg
npm install pg
npx tsc
node dist/server.js
Deno 2.7
// server.ts
import { serve } from "https://deno.land/std@0.224.0/http/server.ts";
// Deno has built-in PostgreSQL support via node:postgres or external packages
// Using npm: specifier for pg
import { Pool } from "npm:pg";
const pool = new Pool({
connectionString: Deno.env.get("DATABASE_URL"),
});
interface User {
id: number;
name: string;
email: string;
}
await serve(async (req) => {
const url = new URL(req.url);
if (url.pathname === "/api/users" && req.method === "GET") {
try {
const { rows } = await pool.query<User>("SELECT * FROM users");
return new Response(JSON.stringify(rows), {
headers: { "Content-Type": "application/json" },
});
} catch {
return new Response(
JSON.stringify({ error: "Internal server error" }),
{ status: 500 }
);
}
}
return new Response(JSON.stringify({ error: "Not found" }), { status: 404 });
}, { port: 3000 });
console.log("Server running on http://localhost:3000");
# Run — one command, no install needed
deno run --allow-net=:3000 --allow-env server.ts
Bun 1.3
// server.ts
// Bun has built-in Postgres client — no external package needed
import { sql } from "bun";
interface User {
id: number;
name: string;
email: string;
}
const server = Bun.serve({
port: 3000,
async fetch(req) {
const url = new URL(req.url);
if (url.pathname === "/api/users" && req.method === "GET") {
try {
const users = await sql<User>`SELECT * FROM users`;
return new Response(JSON.stringify(users), {
headers: { "Content-Type": "application/json" },
});
} catch {
return new Response(
JSON.stringify({ error: "Internal server error" }),
{ status: 500 }
);
}
}
return new Response(JSON.stringify({ error: "Not found" }), { status: 404 });
},
});
console.log(`Server running on http://localhost:${server.port}`);
# Run — no external packages needed for Postgres
bun run server.ts
Notice the difference? Bun's built-in sql tag eliminates the entire pg dependency. Deno's serve() is cleaner than Node's http.createServer(). TypeScript on Node requires the most boilerplate but gives you the most control.
Real-World Use Cases: Where Each Tool Shines
When to Use TypeScript 6.0
Large codebases where type safety prevents production fires. Teams that need strict contracts between frontend and backend. Projects already on Node.js that want type-checking without changing runtimes.
Any project where strict: true (now default) catches real bugs before deployment.
The reality: you're probably already using TypeScript. The question is what runtime you run it on.
When to Use Deno 2.7
Security-sensitive applications — fintech, healthcare, auth systems. Edge deployments via Deno Deploy's global network (now GA). Projects where you want a single tool instead of a toolchain.
TypeScript-heavy projects that want zero-config TS execution. Running untrusted code via Deno Sandbox (new Linux microVMs). Teams that want built-in OpenTelemetry for monitoring logs, metrics, and traces.
Windows ARM developers (new in 2.7). Projects needing Temporal API (stabilized in 2.7).
Deno is the choice when you care about security, simplicity, and observability over ecosystem familiarity.
When to Use Bun 1.3
Speed-critical applications — CI/CD pipelines, test suites, dev servers. Projects already on Node.js that want a drop-in speed boost. Teams using Vercel (native Bun runtime support with full API access).
Cloud-first applications: built-in S3 client (Bun.s3), built-in Postgres client (Bun.sql) — no need for @aws-sdk/client-s3 or pg packages.
AI/ML tooling: Anthropic acquisition means Bun powers Claude Code and Claude Agent SDK. Developers needing TC39 standard ES decorators (new in 1.3). Windows ARM64 developers (new in 1.3). Projects needing OS-level cron jobs (Bun.cron in 1.3).
Bun is the choice when speed matters, you want built-in cloud APIs, and you don't want to change your workflow.
Decision Matrix
Still unsure? Here's a quick decision matrix based on your primary concern.
| Your primary concern | Best choice | Why |
|---|---|---|
| Type safety | TypeScript 6.0 | Full type-checking, strict by default |
| Security | Deno 2.7 | Permissions model, sandboxing |
| Speed | Bun 1.3 | Fastest startup, fastest installs |
| Node.js compatibility | Bun 1.3 | Drop-in replacement, runs Node test suite |
| All-in-one toolchain | Deno 2.7 or Bun 1.3 | Both bundle everything |
| Edge deployment | Deno 2.7 | Deno Deploy GA, global network |
| Vercel deployment | Bun 1.3 | Native runtime support |
| AI/ML integration | Bun 1.3 | Anthropic acquisition, Claude Code |
| Large enterprise codebase | TypeScript 6.0 + Node | Ecosystem maturity, tooling |
| Windows ARM | Both Deno 2.7 and Bun 1.3 | Native support in both |
| Temporal API | Deno 2.7 | Stabilized and built-in |
| Zero-config TypeScript | Deno 2.7 | deno run file.ts just works |
The 2026 Landscape: What Just Changed
TypeScript 6.0: The Last of Its Kind
This is the final release based on the JavaScript codebase. TypeScript 7.0 (Project Corsa) is being rewritten in Go — 10x speedup, native compilation, shared-memory parallelism.
Microsoft chose Go over Rust and C# for speed of native code, shared-memory multi-threading, and a faster development cycle. That decision matters. TS 6.0 is a bridge release — most changes prepare for TS 7.0 adoption.
New --stableTypeOrdering flag helps diagnose differences between TS 6.0 and 7.0. Use it now to prepare for the migration.
TypeScript 6.0 is a bridge. TS 7.0 is the destination. Upgrade to 6.0 now, fix deprecations, then move to 7.0.
Deno 2.7: Maturity, Temporal API, and the JavaScript Trademark Fight
Temporal API stabilization: the long-awaited date/time API is now standard in Deno. No more date-fns or moment for basic date operations.
Windows ARM builds: Deno now runs natively on Windows on ARM devices. npm overrides in package.json: fine-grained control over dependency resolution. Brotli compression streams: native support without external packages. Self-extracting compiled binaries: deno compile produces truly standalone executables.
deno create: new command for scaffolding projects. Deno Deploy GA (February 2026): production-ready edge hosting. Deno Sandbox: instant Linux microVMs for running untrusted code with defense-in-depth security.
The Oracle JavaScript trademark fight (#FreeJavaScript): Deno's legal battle is entering the discovery phase. This matters because it affects how the entire ecosystem talks about itself.
Deno's response to "reports of Deno's demise" — the project is very much alive.
Deno 2.7 is about maturity: Temporal API, Windows ARM, npm overrides, and a real enterprise story with Deploy GA.
Bun 1.3: The Anthropic Acquisition Changes Everything
Bun acquired by Anthropic: now the infrastructure powering Claude Code, Claude Agent SDK, and future AI coding products. This isn't a side project anymore. It's central to Anthropic's developer tooling strategy.
Vercel native Bun runtime: deploy Bun functions directly with full API access. TC39 standard ES decorators: proper decorator support matching the JavaScript standard. Windows ARM64 support: native binaries for ARM Windows devices. Native REPL: interactive JavaScript/TypeScript shell built-in.
Bun.cron: OS-level cron jobs and expression parsing. Bun.sliceAnsi: ANSI/grapheme-aware string slicing. Richer Bun.markdown: more metadata and formatting options. 500x faster postMessage(string): zero-copy inter-thread communication.
structuredClone up to 25x faster for arrays. Buffer.slice() 1.8x faster. path.parse() up to 7x faster. Upgraded JavaScriptCore with 168x faster deep rope string slicing. bun test --path-ignore-patterns: fine-grained test filtering.
Bun 1.3 is no longer just a runtime. It's AI infrastructure. The Anthropic acquisition means Bun will be the default runtime for Claude's coding tools.
Benchmarks: Our Testing Methodology
We tested startup time, package install speed, HTTP server throughput, TypeScript compilation time, and memory usage. Hardware and environment specs matter — always check what the test ran on before trusting numbers.
Synthetic benchmarks don't reflect your workload. The only benchmark that matters is your own code, your own team, your own deployment target.
Test your own code. Our numbers are a starting point, not a decision.
Migration Guides: Moving Between Runtimes
From Node.js + TypeScript to Deno
What changes: permission model, import syntax (URL imports or npm: specifiers), no node_modules. What stays the same: TypeScript code, most npm packages work via npm: imports.
Permission model adjustments: --allow-read, --allow-net, --allow-env flags. You'll need to add these to your run commands or scripts.
Estimated migration time: small projects (hours), medium projects (days), large projects (weeks).
Deno 2.7 makes this easier: npm overrides in package.json, better Node compat, deno create for scaffolding.
From Node.js + TypeScript to Bun
Drop-in replacement reality check: most projects work with zero changes. Known incompatibilities: some native addons, edge cases in node:crypto, specific C++ addons.
bun.lock migration from package-lock.json or pnpm-lock.yaml — Bun auto-detects and converts. No manual work needed.
Estimated migration time: small projects (minutes), medium projects (hours), large projects (days).
Bun 1.3 makes this easier: near-complete Node test suite compatibility, TC39 decorators, Windows ARM64 support.
From Deno to Bun (or Vice Versa)
Why you'd do this: speed (Bun) vs security (Deno). What breaks: Deno's permission model doesn't exist in Bun. Bun's npm-native approach differs from Deno's URL imports.
Is it worth it? Only if your specific pain point (speed or security) is blocking you. Don't migrate for the sake of migrating.
The Honest Verdict: Where Each Tool Frustrates Us
TypeScript 6.0's Pain Points
tsconfig.json complexity never goes away — it just gets new defaults to break. Language server memory usage on large codebases is still a problem (TS 7.0 in Go should fix this). Compilation step adds friction — every change requires a rebuild or watch process.
The deprecation list is long: es5, baseUrl, outFile, amd, umd, systemjs, classic module resolution. Migrating old projects will hurt.
TypeScript is worth the pain for large projects. For small scripts, it's overkill.
Deno 2.7's Pain Points
Smaller ecosystem: fewer tutorials, fewer Stack Overflow answers, fewer third-party integrations. Permission fatigue: constantly adding --allow-* flags gets old, even though it's the right security model. Learning curve: URL imports, JSR registry, no node_modules — it's a different mental model.
The Oracle JavaScript trademark fight: legal uncertainty around the word "JavaScript" itself. It sounds abstract until it affects your tooling.
Deno is the right choice for security-conscious teams. The ecosystem gap is real but closing.
Bun 1.3's Pain Points
Node.js compatibility edge cases: not 100%, some packages still break (especially native addons). Anthropic acquisition uncertainty: will Bun stay open source? Will it become Claude-exclusive? Roadmap changes? Nobody knows yet.
Windows support: improved with ARM64 in 1.3, but still catching up to macOS/Linux overall. No type-checking: you still need tsc for actual type safety — Bun only transpiles. JavaScriptCore vs V8: some V8-specific APIs may behave differently or be missing.
Bun is the fastest path from Node to better performance. The Anthropic acquisition is the biggest unknown.
What We'd Actually Use for a New Project in 2026
For a large enterprise codebase: TypeScript 6.0 + your existing runtime (probably Node), start testing TS 7.0 native previews.
For a security-sensitive API or microservice: Deno 2.7 — the permissions model, Temporal API, and Deno Sandbox are worth the learning curve.
For a speed-critical internal tool or CI pipeline: Bun 1.3 — the speed gains are real and the migration is nearly zero-effort.
For a cloud-native app with database and storage needs: Bun 1.3 — built-in Bun.sql and Bun.s3 eliminate entire categories of dependencies.
For a frontend-heavy project: TypeScript 6.0 + Vite + your runtime of choice — the ecosystem is unmatched.
For Windows ARM developers: Both Deno 2.7 and Bun 1.3 now support it natively.
The best tool is the one your team will actually use consistently. Don't optimize for benchmarks. Optimize for team velocity.
What's Coming Next
TypeScript 7.0: the Go compiler, expected within a few months, 10x speedup, native previews already available via @typescript/native-preview on npm.
Deno 3.0: speculation based on roadmap — deeper Node compat, JSR growth, Deno Deploy expansion, potential LTS model changes.
Bun post-Anthropic: AI-native runtime features, Claude Code integration, potential changes to Bun's independence and open-source model.
The Node.js factor: Node 24+ continues to improve, petition against AI-generated code in Node.js core, what it means for the landscape.
Why the runtime wars are good for developers: competition drives innovation, all three tools are better because the others exist.
Further Reading and Sources
- TypeScript 6.0 Official Announcement — Daniel Rosenwasser, Microsoft
- TypeScript 7.0 Progress Update (December 2025) — Project Corsa details
- A 10x Faster TypeScript — Anders Hejlsberg on the Go port
- Microsoft TypeScript Devs Explain Why They Chose Go Over Rust, C# — The New Stack
- Deno 2.7 Release Notes — Temporal API, Windows ARM, npm overrides
- Deno 2.6 Release Notes —
dxis the newnpx,deno audit, native source maps - Deno Deploy GA Announcement — Production-ready edge hosting
- Introducing Deno Sandbox — Secure Linux microVMs for untrusted code
- How Deno protects against npm exploits — Security model deep dive
- Reports of Deno's Demise Have Been Greatly Exaggerated — Deno's response to criticism
- Benchmarking AWS Lambda Cold Starts Across JavaScript Runtimes — Performance comparison
- Bun Joins Anthropic — Major acquisition news
- Vercel Adds Native Bun Support — Deployment implications
- Behind The Scenes of Bun Install — How Bun achieves 25x faster installs
- Bun v1.3.11 Release Notes — Latest patch release details
- Bun v1.3.10 Release Notes — Native REPL, ES decorators, Windows ARM64
- Bun 1.3 Announcement — Zero-config frontend dev, unified SQL API, Redis client
- How Bun Supports V8 APIs Without Using V8 — Engineering deep dive (3-part series)
- Wasm vs. JavaScript: Who Wins at a Million Rows? — Performance context
- Will AI Force Code to Evolve or Make It Extinct? — The New Stack
FAQs
Which JavaScript runtime is the fastest in 2026?
Bun is generally the fastest for startup times and package installation, but V8 (used by Deno and Node) still excels in complex, long-running server workloads.
Does Bun support TypeScript out of the box?
Yes, Bun supports TypeScript natively and transpiles it extremely fast. However, it does not perform type-checking during runtime, so you still need tsc or a separate type-checking tool in your pipeline.
What is the key advantage of Deno 2.7?
Deno 2.7 emphasizes a 'secure-by-default' architecture where file and network access require explicit permissions. It also offers excellent npm compatibility and a stabilized Temporal API.
Is TypeScript 6.0 considered a runtime environment?
No, TypeScript is a type-checking layer that compiles to JavaScript. TypeScript 6.0 is the final version built on JavaScript, with version 7.0 being rewritten entirely in Go for a dramatic performance boost.
Work with us
Let's build something together
We build fast, modern websites and applications using Next.js, React, WordPress, Rust, and more. If you have a project in mind or just want to talk through an idea, we'd love to hear from you.