サーバー側でJavaScriptやTypeScriptを動かす選択肢には、Node.js、Deno、Bunがあります。3つは同じECMAScriptを実行しますが、JavaScriptエンジン、標準API、パッケージ解決、権限モデル、同梱ツールが異なります。
先に結論
記事情報: 2026年1月12日初出。各ランタイムの公式資料を2026年7月25日に再確認しています。
固定のベンチマーク表だけでランタイムを選ぶのは適切ではありません。起動時間やHTTP処理性能は、バージョン、OS、CPU、フレームワーク、処理内容で変わるためです。採用時は次の順番で判断します。
- 必須パッケージと組み込みAPIが動くか
- 本番基盤と監視ツールが対応するか
- セキュリティ境界をどう作るか
- テスト・ビルド・依存管理をどこまで統一したいか
- 実際のアプリで性能と安定性を測れるか
既存のNode.jsアプリなら、まずNode.jsを基準にします。BunやDenoへ移る理由が、単なる速度の期待ではなく、組み込みツールや権限管理など具体的な利点として説明できる場合に小さく検証します。

Node.js:互換性と運用経路を優先
Node.jsはV8を使うJavaScriptランタイムです。npmのパッケージ、CommonJSとES Modules、Node-API製ネイティブアドオン、主要な監視・ホスティング環境との組み合わせが広く使われています。
本番ではCurrent版を追い続けるより、Active LTSまたはMaintenance LTSの版を選ぶのが基本です。Node.js公式のリリース表で、各メジャー版の状態とサポート終了日を確認してください。
TypeScriptの扱い
現在のNode.jsは、一定範囲のTypeScriptを型消去して直接実行できます。ただしtsconfig.jsonを読まず、pathsや、JavaScript生成が必要なTypeScript構文には制約があります。型チェックも行わないため、次の2つは別の作業です。
# 実行
node src/index.ts
# 型チェック
npx tsc --noEmit
Node.jsだけでTypeScript開発の全工程が完結するとは考えず、利用バージョンのTypeScript公式設定例を確認します。
Permission Model
Node.jsのPermission Modelは、対象バージョンではstableになっています。--permissionを指定すると、ファイル、ネットワーク、子プロセス、Workerなどを制限できます。
node --permission \
--allow-fs-read=./config \
--allow-net=api.example.com \
server.js
ただし公式資料は、悪意あるコードに対するsandboxではなく、信頼したコードの意図しない操作を防ぐ「seat belt」だと説明しています。OSやコンテナの隔離を置き換える機能ではありません。
Deno:権限を明示し、Web標準を中心にする
DenoもV8を使用し、TypeScript実行、formatter、linter、test runnerなどを提供します。ファイル、ネットワーク、環境変数、子プロセスへのアクセスは既定で許可されず、必要な範囲をCLIで与えます。
deno run \
--allow-read=./config \
--allow-net=api.example.com \
main.ts
--allow-netのように対象を省略するとカテゴリ全体を許可します。-Aはすべてを許可し、sandboxを無効にするため、便利さだけを理由に常用しないでください。
また、同じthreadで動くコードは同じ権限を共有します。依存パッケージごとに別の権限を与える仕組みではありません。--allow-runや--allow-ffiはsandbox外の操作につながるため、公式資料も強い権限として注意を促しています。
npm・Node.js互換
Denoはnpm:指定やpackage.jsonを通じてnpmパッケージを利用でき、Node.js組み込みAPIにも対応を進めています。しかしNode.js固有の内部実装、ネイティブアドオン、install script、ファイル配置を前提にするパッケージでは追加設定が必要な場合があります。
移行時は「npm対応」という一語で済ませず、直接依存と主要な間接依存を実行テストします。特にDBドライバ、画像処理、ブラウザ自動化、監視agentは実環境で確認してください。
Bun:ランタイムと開発ツールをまとめる
BunはJavaScriptCoreを使い、runtime、package manager、test runner、bundlerを1つの実行ファイルで提供します。TypeScriptとJSXを実行時に変換でき、Node.jsのglobals、組み込みmodule、package resolutionとの互換性を目標にしています。
bun install
bun test
bun run src/index.ts
bun build src/index.ts --outdir dist
ツールをまとめられることはBunの明確な特徴です。一方で、Node.js互換性は継続中で、公式互換性ページにも部分対応や挙動差が記載されています。BunはNode.jsと異なるJavaScriptエンジンを使うため、V8固有APIやネイティブアドオンは特に確認が必要です。
Bun固有のHTTP、SQL、S3などのAPIを使うと依存を減らせる可能性がありますが、別ランタイムへ戻す際の変更範囲は増えます。Node.js互換APIを中心にするか、Bun固有機能を採用するかを設計時に決めます。
比較すべき項目
| 観点 | Node.js | Deno | Bun |
|---|---|---|---|
| JavaScriptエンジン | V8 | V8 | JavaScriptCore |
| TypeScript | 対応構文を型消去して実行 | 組み込みで実行・型検査を分離 | 組み込みtranspilerで実行 |
| 権限 | flagで有効化するPermission Model | I/Oを既定で拒否し個別許可 | OS・実行環境側の制御を基本に確認 |
| npm | 基準となる環境 | npm・Node互換を提供 | npm・Node互換を提供 |
| 同梱ツール | runtime中心 | fmt・lint・testなど | install・test・buildなど |
この表は優劣ではなく、確認場所の違いを示しています。たとえば「TypeScriptを直接実行できる」ことは、型チェックが済んでいることを意味しません。3つのどれでも、CIで型チェックを別に実行する設計が必要です。
小さく比較する手順
候補を選ぶときは、同じ最小アプリを3つ作るより、現在のアプリから重要経路を切り出すほうが現実的です。
- 対象ランタイムの版を固定する
- lockfileを含め、クリーン環境で依存を導入する
- unit testと型チェックを実行する
- DB、外部API、file uploadなど主要I/Oを試す
- graceful shutdown、signal、timeoutを確認する
- ログ、trace、profiling、脆弱性検査を接続する
- 本番相当の負荷で自分の指標を測る
性能測定では平均応答時間だけでなく、p95・p99、メモリ、CPU、エラー率、warm-up、起動直後の挙動を記録します。runtime以外の条件をそろえ、差が運用複雑性を上回るかを判断します。
選び方
Node.jsは、既存資産と運用互換性を最優先する場合の基準です。Denoは、権限を明示する実行モデルとWeb標準中心のツールチェーンを採用したい場合に検討できます。Bunは、runtimeとpackage management、test、buildを統合したい場合に候補になります。
どれか1つがすべての用途で優れるわけではありません。ランタイムを変えず、Bunのpackage managerだけを試すなど段階導入も可能です。導入理由、戻す条件、検証結果を残し、公式の互換性・リリースページを更新時に再確認してください。