Node.js
Chrome V8 エンジン上で動作するサーバーサイド JavaScript ランタイム
Node.js とは
Node.js は、Chrome の V8 JavaScript エンジンをベースにしたサーバーサイドランタイムである。2009 年に Ryan Dahl が公開し、ノンブロッキング I/O とイベントループの組み合わせによって、接続ごとにスレッドを割り当てずに大量の同時接続をさばけるのが特徴。AWS Lambda が公式に提供するランタイムの 1 つでもあり、サーバーレスの入り口としてもよく使われる。
リリース系列と保守期限
メジャー版は最初の 6 ヶ月を Current として過ごす。Node.js 26 までは偶数番の版だけがそのあと Active LTS へ移り、奇数番はおおむね 6 ヶ月でサポートが切れる。LTS へ入った版は重大なバグ修正が通算 30 ヶ月保証され、公式の指針も「本番アプリケーションは Active LTS か Maintenance LTS の版だけを使う」と明確に書いている。
2026 年 8 月時点の内訳は、26 が Current (2026 年 5 月リリース)、24 (Krypton) と 22 (Jod) が LTS、20 と 23、25 はすでに EOL である。なお Node.js 27 以降はこの周期自体が変わり、メジャー版のリリースは年 1 回になって、すべてのメジャー版が Current 期間を経て LTS へ入る方式に移行する予定になっている。
版を上げる動機は新機能よりも保守期限にある。EOL 版は脆弱性が見つかっても修正が出ないため、稼働中のアプリケーションでは「使っている LTS が切れる前に次の LTS へ移る」を定例作業として先に予定へ置いておく。
シングルスレッド + イベントループ
Node.js が単一スレッドで回しているのは JavaScript の実行 (イベントループ) であり、プロセス自体は複数のスレッドを持つ。イベントループがノンブロッキング I/O を束ねることで、接続ごとにスレッドを立てずに大量の同時接続を処理できる。
リクエスト → イベントループ → I/O 操作 (非同期) → コールバック → レスポンス
↑ |
└────────────────────────────────────┘
I/O の待ちを裏で受け持つのは libuv のスレッドプール (既定 4 スレッド) である。同期版を除くファイルシステム API、dns.lookup() と dns.lookupService()、crypto.pbkdf2() のような重い暗号処理、非同期版の zlib がここを通る。一方でネットワーク I/O はプールを使わず、イベントループが OS の通知機構を直接見ている。
CPU バウンドな処理 (画像変換、暗号計算) は JavaScript のスレッドを占有してイベントループを止めるため、worker_threads で別スレッドへ逃がすか、外部サービスに委譲する。
Node.js vs Deno vs Bun
3 つのランタイムの違いを、選定で効いてくる観点に絞って並べる。
| 観点 | Node.js | Deno | Bun |
|---|---|---|---|
| エンジン | V8 | V8 | JavaScriptCore |
| パッケージ | npm | URL import / npm | npm |
| TypeScript | 型注釈を除去して直接実行 | ネイティブ対応 | ネイティブ対応 |
| セキュリティ | --permission で制限可 (既定は無制限) | 既定で拒否・明示的に許可 | 制限なし |
| エコシステム | 最大 | 成長中 | 成長中 |
この 2 行は近年 Node.js 側が埋めてきた差である。TypeScript の直接実行は v22.6.0 で入り、v23.6.0 と v22.18.0 で既定有効、v25.2.0 と v24.12.0 で安定扱いになった。ただし Node.js がするのは消去可能な型構文を空白に置き換えることだけで、型検査は一切しない。tsconfig.json も読まないため、パスエイリアスや古い構文へのダウンレベルが必要なら外部のツールが依然として必要になる。
パーミッションモデルは v20.0.0 で入り、v23.5.0 と v22.13.0 で安定になった。--permission を付けて起動するとファイルシステム・ネットワーク・子プロセス生成・worker_threads・ネイティブアドオンなどが制限され、違反は ERR_ACCESS_DENIED になる。ただし公式ドキュメントはこれを「シートベルト」と表現し、信頼したコードの不注意な操作を止める仕組みであって悪意あるコードは防げないと明記している。Deno の既定拒否と同じ強度のものとして並べるのは適切ではない。
Node.js の最大の強みはエコシステムの規模で、npm レジストリの公開パッケージ数は言語エコシステムの中でも最大級である。実務で困るのはライブラリが見つからないことよりも、候補が多すぎて保守状況と依存関係の見極めに時間がかかることのほうだ。
Lambda での Node.js
Lambda は Node.js を公式ランタイムとして提供している。2026 年 8 月時点で本番に使えるのは nodejs22.x と nodejs24.x で、nodejs26.x はパブリックプレビュー扱い (SLA とテクニカルサポートの対象外) なので本番では選ばない。nodejs24.x の廃止予定日は 2028 年 4 月 30 日で、廃止後は関数の作成、さらに後日は更新もブロックされる。ランタイムの提供期限は Node.js 本体の LTS 期限とは別に管理されているため、両方を見ておく必要がある。
初期化時間の桁感はランタイムの系統でおおよそ分かれる。次の値は目安で、実際にはデプロイパッケージのサイズ、割り当てメモリ、VPC 構成、初期化コードの中身で大きく動く。
| 観点 | Node.js | Python | Java |
|---|---|---|---|
| コールドスタート | 100〜300 ms 程度 | 100〜300 ms 程度 | 1〜5 秒程度 |
| 実行速度 | 高速 | 中程度 | 高速 |
| メモリ効率 | 良好 | 良好 | 大きい |
Java が不利になりやすいのは JVM の起動とクラスロードが初期化に乗るためで、逆に言えば初期化をどれだけ軽くできるかで差は縮む。Node.js でも SDK クライアントの生成や設定の読み込みをハンドラーの外に出して実行環境の再利用に乗せるかどうかで、体感の初期化時間は変わる。
CommonJS vs ES Modules
CommonJS と ES Modules のコード例を比較する。
// CommonJS (従来)
const fs = require('fs');
module.exports = { handler };
// ES Modules
import { readFile } from 'node:fs/promises';
export const handler = async (event) => { /* ... */ };
Lambda は ES Modules をサポートしており、package.json に "type": "module" を指定するか、ファイル拡張子を .mjs にする。
2 つの形式は長く一方通行で、CommonJS から ES Modules を読む手段がなかった。require() による ES Modules の読み込みは v22.0.0 と v20.17.0 で追加され、v23.0.0・v22.12.0・v20.19.0 でフラグ不要になり、v25.4.0 で安定扱いになった。条件は読み込まれる側が完全に同期であること、つまりトップレベル await を含まないことである。ES Modules 化した依存パッケージに ERR_REQUIRE_ESM で阻まれてアプリ側を丸ごと書き換える、という作業は新しい版では避けられる。
よくある落とし穴
- イベントループのブロック:
JSON.parseは同期 API なので、数十 MB の JSON を渡すとパースが終わるまで他のリクエストが 1 つも進まない。ストリーミングパーサーを使うか、巨大な JSON を 1 リクエストで受けない設計にする - メモリリーク: Lambda は実行環境を再利用するため、ハンドラー外のグローバル変数やクロージャにデータを足し続けると呼び出しをまたいで蓄積し、やがてメモリ上限に達して失敗する。キャッシュを置くなら件数か寿命の上限を必ず付ける
- コールバック地獄:
async/awaitを使わずにコールバックをネストすると可読性が崩壊する。エラー処理が階層ごとに散るため、握り潰しの見落としも増える node_modulesの肥大化: .zip 形式のデプロイパッケージは展開後 250 MB が上限で、この値は Lambda Layer の中身も合算した合計に対して効く。レイヤーへ追い出しても総量は減らないため、対策はバンドラーによる不要コードの削除 (Tree Shaking) か、上限が別に定められているコンテナイメージ形式への移行になる
実務で効いてくるのは、言語機能よりも「イベントループを止めない」と「使っている版の保守期限を把握する」の 2 点である。前者はイベントループ遅延やプロファイルを数値として見えるようにしておくこと、後者は LTS の終了予定日を移行作業の予定として先に置いておくことで扱える。
関連書籍も参考になる。
この記事は役に立ちましたか?
関連用語
イベントループ
Node.js のシングルスレッドで非同期 I/O を実現する実行モデル
非同期プログラミング
I/O 待ちの間に他の処理を進め、システムのスループットを向上させるプログラミング手法
Lambda
AWS のサーバーレスコンピューティングサービスで、コードをイベント駆動で実行する
コールドスタート
Lambda の初回呼び出し時に実行環境の初期化が発生し、レイテンシが増加する現象
Worker Threads
Node.js で CPU 集約的な処理をメインスレッドをブロックせずに別スレッドで実行する仕組み
並行処理 (Concurrency) とは - 並列処理 (Parallelism) との違い
Concurrency (並行処理) の意味を解説。複数のタスクを論理的に同時進行させる手法で、物理的に同時実行する並列処理 (Parallelism) とは区別される。Node.js / Go / Rust の並行処理モデルの違いも紹介。
関連する記事
DevOps 本ガイド - CI/CD とインフラ自動化を学ぶ技術書の選び方
DevOps の文化と原則から CI/CD、IaC、オブザーバビリティまで学べる技術書の選び方と学習順序を紹介します。
インフラ / クラウド本ガイド - AWS や Docker を本で学ぶ
クラウドインフラ、コンテナ、IaC を学べる技術書の選び方と学習順序を紹介。インフラ本の賞味期限問題と公式ドキュメントとの使い分けも解説します。
JavaScript / TypeScript 本ガイド - 入門から型で守る実務コードまで
JavaScript と TypeScript を 1 本の学習ルートとして捉えた技術書の選び方。JavaScript の入門書、言語の背骨を通す体系書、TypeScript の型システムを設計の武器にする本、React/Next.js の実践書まで 2026 年 8 月時点の定番で案内します。