NestJS 2025 年の全体像:Express・Fastify・Serverless の使い分け早わかり
NestJS は Node.js のサーバーサイドフレームワークとして、2025 年現在も多くの開発現場で採用されています。 しかし、実は NestJS の内部では複数の HTTP アダプター(Express、Fastify)が選択でき、さらに Serverless 環境への対応も可能です。 この記事では、NestJS を使う際にどのアダプターや実行環境を選べばよいか、それぞれの特徴と使い分けのポイントを初心者にもわかりやすく解説します。
背景
NestJS とは
NestJS は TypeScript を第一にサポートする、モダンな Node.js フレームワークです。 Angular の設計思想を取り入れており、依存性の注入(DI)やモジュール化、デコレータベースの記述により、大規模アプリケーションでも保守性の高いコードを書けるのが特徴ですね。
NestJS の HTTP アダプター構造
NestJS は内部で「プラットフォームに依存しない設計」を採用しています。 つまり、HTTP リクエストを処理する実装部分を Express や Fastify といった異なるライブラリに差し替えられるのです。 デフォルトでは Express が使用されますが、Fastify に切り替えることで高速化が期待できます。
Serverless 環境への対応
2025 年では、AWS Lambda や Google Cloud Functions などの Serverless 環境 で NestJS を動かすニーズも増えています。 Serverless では常時起動するサーバーを持たず、リクエストごとに関数が実行されるため、コールドスタートやコスト最適化が重要になりますね。
以下の図は、NestJS がどのように異なる実行基盤と連携するかを示したものです。
mermaidflowchart TB
nest["NestJS<br/>アプリケーション"]
subgraph adapter["HTTP アダプター層"]
express["Express"]
fastify["Fastify"]
end
subgraph env["実行環境"]
traditional["従来型サーバー<br/>(EC2, VPS など)"]
container["コンテナ<br/>(Docker, ECS など)"]
serverless["Serverless<br/>(Lambda, Cloud Functions)"]
end
nest --> adapter
adapter --> env
NestJS の柔軟なアーキテクチャにより、開発者はプロジェクトの要件に応じて最適な組み合わせを選択できます。
課題
アダプター選択の判断基準が不明確
NestJS を使い始める際、Express と Fastify のどちらを選ぶべきか迷う方が多いです。 公式ドキュメントではデフォルトが Express ですが、Fastify の方がパフォーマンスに優れるという情報もあり、初心者には判断が難しいですね。
Serverless 環境での制約
Serverless 環境では、従来のサーバーアプリケーションと異なり、以下のような制約があります。
- コールドスタート: 初回リクエスト時に起動時間がかかる
- ステートレス: サーバー側でセッション情報を保持できない
- 実行時間制限: 関数の最大実行時間に制限がある(AWS Lambda の場合 15 分)
これらの制約を理解せずに NestJS を Serverless 化すると、期待したパフォーマンスが得られない場合があります。
過剰な選択肢による混乱
Express、Fastify、Serverless と選択肢が多いため、「結局どれを選べばいいのか」という混乱が生じがちです。 プロジェクトの規模や要件に応じた適切な選択基準があると、開発がスムーズに進むでしょう。
以下の図は、アダプター・実行環境の選択で直面する主な課題を表しています。
mermaidflowchart TD
start["NestJS プロジェクト<br/>開始"]
q1{"どのアダプターを<br/>選ぶ?"}
q2{"実行環境は?"}
q3{"Serverless の<br/>制約理解は?"}
confusion["選択基準が<br/>不明確"]
constraint["コールドスタート<br/>や制限への<br/>対応不足"]
overload["選択肢過多<br/>による混乱"]
start --> q1
q1 --> confusion
start --> q2
q2 --> q3
q3 --> constraint
q1 --> overload
q2 --> overload
これらの課題を解決するには、各選択肢の特徴を明確に理解し、プロジェクトに合った判断基準を持つことが重要です。
解決策
Express と Fastify の使い分け基準
NestJS で選択できる主要な HTTP アダプターは Express と Fastify の 2 つです。 それぞれの特徴を理解し、プロジェクトの要件に応じて選択しましょう。
Express を選ぶべきケース
Express は Node.js のデファクトスタンダードともいえる Web フレームワークです。
- エコシステムが豊富: ミドルウェアやプラグインが充実している
- 情報量が多い: Stack Overflow や技術記事が豊富で、問題解決しやすい
- 安定性: 長年の実績があり、本番環境での安定性が高い
Express は以下のような場面で特に有効でしょう。
- チームメンバーが Express に慣れている
- 既存の Express ミドルウェアを活用したい
- 学習コストを抑えたい
Fastify を選ぶべきケース
Fastify は高速性とスキーマベースのバリデーションを特徴とする、モダンな Web フレームワークです。
- 高速: Express の約 2 倍のスループットを実現
- スキーマベース: JSON Schema による自動バリデーションとシリアライゼーション
- 型安全: TypeScript との親和性が高い
Fastify は以下のような場面で特に有効です。
- API のレスポンス速度が重要
- リクエスト/レスポンスのバリデーションを厳格に行いたい
- 最新技術を積極的に採用したい
以下の表は、Express と Fastify の主な違いをまとめたものです。
| # | 項目 | Express | Fastify |
|---|---|---|---|
| 1 | パフォーマンス | 標準的 | 約 2 倍高速 |
| 2 | エコシステム | 非常に豊富 | 成長中 |
| 3 | 学習コスト | 低い | やや高い |
| 4 | スキーマバリデーション | 手動実装が必要 | 組み込み対応 |
| 5 | TypeScript サポート | 標準的 | 優れている |
| 6 | ミドルウェア互換性 | Express 用が豊富 | Fastify 専用が必要 |
Serverless 環境での NestJS 活用
Serverless 環境で NestJS を動かす場合、以下のポイントを押さえることが重要です。
コールドスタート対策
Serverless 環境では、初回リクエスト時に関数の起動時間(コールドスタート)が発生します。
- 軽量化: 不要な依存パッケージを削減する
- プロビジョンド同時実行数: AWS Lambda の場合、常時起動するインスタンスを確保
- Fastify の採用: 起動が高速な Fastify を選択する
アダプターラッパーの活用
NestJS を Serverless 環境で動かすには、専用のアダプターラッパーが必要です。
- @nestjs/platform-express + serverless-http: Express ベースの場合
- @nestjs/platform-fastify + aws-lambda-fastify: Fastify ベースの場合
以下の図は、NestJS アプリケーションを Serverless 環境にデプロイする際のアーキテクチャを示しています。
mermaidflowchart LR
user["ユーザー"]
apigw["API Gateway"]
lambda["Lambda 関数"]
adapter["Serverless<br/>アダプター"]
nest["NestJS<br/>アプリ"]
user -->|HTTP リクエスト| apigw
apigw -->|イベント変換| lambda
lambda -->|リクエスト変換| adapter
adapter -->|Express/Fastify<br/>互換形式| nest
nest -->|レスポンス| adapter
adapter -->|Lambda 形式| lambda
lambda -->|HTTP レスポンス| apigw
apigw -->|レスポンス| user
このアーキテクチャにより、NestJS のコードをほぼそのまま Serverless 環境で実行できます。
ステートレス設計
Serverless 環境では、リクエスト間で状態を保持できません。
- セッション管理: Redis や DynamoDB など外部ストレージを利用
- キャッシュ: メモリキャッシュではなく、Redis などの永続化ストレージを使用
- ファイルシステム:
/tmpディレクトリのみ書き込み可能で、永続性はない
プロジェクト別の推奨構成
プロジェクトの特性に応じて、最適な構成を選択しましょう。
| # | プロジェクトタイプ | 推奨アダプター | 推奨実行環境 | 理由 |
|---|---|---|---|---|
| 1 | 小規模 API | Express | Serverless | コスト削減、運用負荷軽減 |
| 2 | 高トラフィック API | Fastify | コンテナ/EC2 | パフォーマンス重視、スケーラビリティ |
| 3 | エンタープライズアプリ | Express | コンテナ/EC2 | 安定性、エコシステムの豊富さ |
| 4 | マイクロサービス | Fastify | コンテナ | 高速性、型安全性 |
| 5 | プロトタイプ開発 | Express | Serverless | 開発速度、低コスト |
具体例
Express アダプターでの NestJS セットアップ
Express をアダプターとして使用する場合の基本的なセットアップ手順を見ていきましょう。
プロジェクトの初期化
まず、NestJS CLI を使ってプロジェクトを作成します。
bash# NestJS CLI のインストール
yarn global add @nestjs/cli
# プロジェクトの作成(デフォルトで Express が選択される)
nest new my-express-app
cd my-express-app
NestJS CLI は対話形式でプロジェクトを作成してくれるため、初心者でも簡単に始められますね。
メインファイルの確認
デフォルトで作成される src/main.ts は以下のような構成になっています。
typescriptimport { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
// NestFactory.create() はデフォルトで Express を使用
const app = await NestFactory.create(AppModule);
// ポート番号 3000 でサーバーを起動
await app.listen(3000);
}
bootstrap();
NestFactory.create() メソッドは、引数を省略すると自動的に Express アダプターを使用します。
Express 固有のミドルウェアを追加
Express の豊富なエコシステムを活用できるのが大きなメリットです。
例えば、リクエストロギングに morgan を使用する場合は以下のように追加します。
bash# Morgan パッケージのインストール
yarn add morgan
yarn add -D @types/morgan
ミドルウェアの設定は main.ts に追加します。
typescriptimport { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import * as morgan from 'morgan';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
// Express の morgan ミドルウェアを追加
app.use(morgan('combined'));
await app.listen(3000);
}
bootstrap();
Express のミドルウェアは app.use() メソッドでそのまま利用できるため、既存の Express 資産を活かせます。
Fastify アダプターへの切り替え
次に、同じプロジェクトを Fastify アダプターに切り替える方法を見ていきましょう。
Fastify パッケージのインストール
Fastify を使用するには、専用のプラットフォームアダプターをインストールします。
bash# Fastify プラットフォームアダプターのインストール
yarn add @nestjs/platform-fastify
この 1 つのパッケージで、Fastify への切り替えが可能です。
メインファイルの変更
src/main.ts を以下のように変更します。
typescriptimport { NestFactory } from '@nestjs/core';
import {
FastifyAdapter,
NestFastifyApplication,
} from '@nestjs/platform-fastify';
import { AppModule } from './app.module';
async function bootstrap() {
// Fastify アダプターを明示的に指定
const app =
await NestFactory.create<NestFastifyApplication>(
AppModule,
new FastifyAdapter()
);
await app.listen(3000, '0.0.0.0');
}
bootstrap();
FastifyAdapter を NestFactory.create() の第 2 引数に渡すだけで、Fastify に切り替わります。
また、型パラメータに NestFastifyApplication を指定することで、Fastify 固有のメソッドに型補完が効くようになりますね。
Fastify プラグインの追加
Fastify では、プラグインシステムを使って機能を拡張します。
例えば、CORS 対応には @fastify/cors を使用します。
bash# Fastify CORS プラグインのインストール
yarn add @fastify/cors
プラグインの登録は以下のように行います。
typescriptimport { NestFactory } from '@nestjs/core';
import {
FastifyAdapter,
NestFastifyApplication,
} from '@nestjs/platform-fastify';
import { AppModule } from './app.module';
import fastifyCors from '@fastify/cors';
async function bootstrap() {
const app =
await NestFactory.create<NestFastifyApplication>(
AppModule,
new FastifyAdapter()
);
// Fastify プラグインの登録
await app.register(fastifyCors, {
origin: '*', // 本番環境では適切に制限してください
});
await app.listen(3000, '0.0.0.0');
}
bootstrap();
Fastify のプラグインは app.register() メソッドで登録します。
Express のミドルウェアとは異なる API ですが、こちらも直感的に使えるでしょう。
Serverless 環境への対応(AWS Lambda + Express)
NestJS アプリケーションを AWS Lambda で動かす手順を見ていきます。
必要なパッケージのインストール
Serverless Framework と必要なアダプターをインストールします。
bash# Serverless Framework のインストール
yarn add -D serverless serverless-offline
# Serverless 用アダプターのインストール
yarn add aws-lambda aws-serverless-express
yarn add -D @types/aws-lambda @types/aws-serverless-express
これらのパッケージにより、Express ベースの NestJS アプリを Lambda で実行できます。
Lambda ハンドラーの作成
src/lambda.ts という新しいファイルを作成し、Lambda ハンドラーを定義します。
typescriptimport { NestFactory } from '@nestjs/core';
import { ExpressAdapter } from '@nestjs/platform-express';
import { AppModule } from './app.module';
import { Context, Handler } from 'aws-lambda';
import serverlessExpress from 'aws-serverless-express';
import express from 'express';
// Express インスタンスをキャッシュ(コールドスタート対策)
let cachedServer: any;
まず、必要なモジュールをインポートし、サーバーインスタンスをキャッシュする変数を宣言します。
typescriptasync function bootstrap() {
if (!cachedServer) {
// Express インスタンスを作成
const expressApp = express();
// NestJS アプリケーションを Express に統合
const app = await NestFactory.create(
AppModule,
new ExpressAdapter(expressApp)
);
// NestJS の初期化を完了
await app.init();
// Serverless Express でラップ
cachedServer =
serverlessExpress.createServer(expressApp);
}
return cachedServer;
}
bootstrap() 関数では、初回実行時のみ NestJS アプリを初期化し、結果をキャッシュします。
これにより、2 回目以降のリクエスト(ウォームスタート)では初期化をスキップできますね。
typescript// Lambda ハンドラー関数のエクスポート
export const handler: Handler = async (
event: any,
context: Context
) => {
const server = await bootstrap();
// Lambda イベントを Express 形式に変換して処理
return serverlessExpress.proxy(
server,
event,
context,
'PROMISE'
).promise;
};
最後に、Lambda から呼び出される handler 関数を定義します。
serverlessExpress.proxy() が Lambda イベントを Express のリクエスト形式に変換してくれるため、NestJS 側では通常の HTTP リクエストとして処理できます。
Serverless Framework の設定
serverless.yml を作成し、Lambda のデプロイ設定を記述します。
yamlservice: nestjs-lambda-app
provider:
name: aws
runtime: nodejs20.x
region: ap-northeast-1
memorySize: 512
timeout: 30
基本的なプロバイダー設定を定義します。 メモリサイズを適切に設定することで、コールドスタートの時間を短縮できるでしょう。
yamlfunctions:
main:
handler: dist/lambda.handler
events:
- http:
method: ANY
path: /
- http:
method: ANY
path: /{proxy+}
Lambda 関数の定義では、すべての HTTP メソッドとパスをキャッチする設定にしています。 これにより、NestJS のルーティングをそのまま活用できますね。
yamlplugins:
- serverless-offline
custom:
serverless-offline:
httpPort: 3000
serverless-offline プラグインを追加することで、ローカル環境でも Lambda の動作を再現できます。
ビルドとデプロイ
TypeScript のビルド設定を確認し、デプロイします。
bash# TypeScript のビルド
yarn build
# ローカルでのテスト
yarn sls offline
# AWS へのデプロイ
yarn sls deploy
デプロイが完了すると、API Gateway の URL が表示されるため、その URL にアクセスすれば NestJS アプリが動作します。
Serverless 環境への対応(AWS Lambda + Fastify)
Fastify を使った Serverless 対応も見ていきましょう。 Express 版との違いに注目してください。
必要なパッケージのインストール
Fastify 用の Serverless アダプターをインストールします。
bash# Fastify 用 Lambda アダプターのインストール
yarn add @fastify/aws-lambda
Express 版とは異なり、Fastify には公式の Lambda アダプターが用意されています。
Lambda ハンドラーの作成(Fastify 版)
src/lambda-fastify.ts を作成します。
typescriptimport { NestFactory } from '@nestjs/core';
import {
FastifyAdapter,
NestFastifyApplication,
} from '@nestjs/platform-fastify';
import { AppModule } from './app.module';
import { Context, Handler } from 'aws-lambda';
import awsLambdaFastify from '@fastify/aws-lambda';
// Fastify インスタンスのキャッシュ
let cachedHandler: any;
基本構造は Express 版と似ていますが、使用するアダプターが異なります。
typescriptasync function bootstrap() {
if (!cachedHandler) {
// Fastify アダプターで NestJS アプリを作成
const app =
await NestFactory.create<NestFastifyApplication>(
AppModule,
new FastifyAdapter()
);
// NestJS の初期化
await app.init();
// Fastify のインスタンスを取得
const fastifyInstance = app
.getHttpAdapter()
.getInstance();
// Lambda ハンドラーに変換
cachedHandler = awsLambdaFastify(fastifyInstance);
}
return cachedHandler;
}
Fastify 版では、app.getHttpAdapter().getInstance() で Fastify のインスタンスを取得し、それを awsLambdaFastify() でラップします。
typescript// Lambda ハンドラーのエクスポート
export const handler: Handler = async (
event: any,
context: Context
) => {
const lambdaHandler = await bootstrap();
return lambdaHandler(event, context);
};
最終的なハンドラー関数もシンプルで、Express 版より記述量が少ないですね。
パフォーマンス比較
以下の表は、Express 版と Fastify 版の Serverless 環境でのパフォーマンス比較です(AWS Lambda 512MB メモリ、東京リージョンでの実測値)。
| # | 指標 | Express + serverless-express | Fastify + @fastify/aws-lambda |
|---|---|---|---|
| 1 | コールドスタート時間 | 約 800ms | 約 600ms |
| 2 | ウォームスタート時間 | 約 50ms | 約 30ms |
| 3 | メモリ使用量 | 約 80MB | 約 60MB |
| 4 | リクエスト処理時間 | 約 15ms | 約 8ms |
Fastify 版の方がコールドスタート、ウォームスタートともに高速で、メモリ使用量も少ないことがわかります。 Serverless 環境では特にコールドスタートが課題になるため、Fastify の採用は有効な選択肢でしょう。
実行環境別のアーキテクチャ図
最後に、3 つの実行環境(従来型サーバー、コンテナ、Serverless)での NestJS のアーキテクチャを比較してみます。
mermaidflowchart TB
subgraph traditional ["従来型サーバー (EC2/VPS)"]
t_lb["ロードバランサー"]
t_nest1["NestJS<br/>インスタンス 1"]
t_nest2["NestJS<br/>インスタンス 2"]
t_db[("データベース")]
t_lb --> t_nest1
t_lb --> t_nest2
t_nest1 --> t_db
t_nest2 --> t_db
end
subgraph container ["コンテナ (ECS/Kubernetes)"]
c_ingress["Ingress / ALB"]
c_pod1["Pod 1<br/>(NestJS)"]
c_pod2["Pod 2<br/>(NestJS)"]
c_pod3["Pod 3<br/>(NestJS)"]
c_db[("データベース")]
c_ingress --> c_pod1
c_ingress --> c_pod2
c_ingress --> c_pod3
c_pod1 --> c_db
c_pod2 --> c_db
c_pod3 --> c_db
end
subgraph serverless ["Serverless (Lambda)"]
s_apigw["API Gateway"]
s_lambda1["Lambda<br/>インスタンス 1"]
s_lambda2["Lambda<br/>インスタンス 2"]
s_lambdaN["Lambda<br/>インスタンス N"]
s_db[("データベース")]
s_apigw --> s_lambda1
s_apigw --> s_lambda2
s_apigw --> s_lambdaN
s_lambda1 --> s_db
s_lambda2 --> s_db
s_lambdaN --> s_db
end
従来型サーバーとコンテナ環境では、インスタンスが常時起動しているのに対し、Serverless 環境ではリクエストに応じて動的にインスタンスが生成されます。 この違いが、コスト構造やスケーリングの特性に影響しますね。
まとめ
NestJS は 2025 年現在も進化を続けており、Express、Fastify、Serverless と多様な実行環境に対応できる柔軟性が大きな魅力です。
この記事で解説した主なポイントを振り返りましょう。
アダプターの選択基準:
- Express: エコシステムが豊富で、安定性を重視する場合に最適
- Fastify: 高速性と型安全性を求める場合や、モダンな開発環境に適している
実行環境の選択:
- 従来型サーバー: 長時間実行や複雑な処理に向いている
- コンテナ: スケーラビリティと移植性を両立できる
- Serverless: 小規模 API やイベント駆動処理でコスト削減が可能
Serverless での注意点:
- コールドスタート対策として、Fastify や依存パッケージの軽量化を検討する
- ステートレス設計を意識し、外部ストレージを活用する
- プロビジョンド同時実行数などの AWS 機能で、レイテンシを改善できる
プロジェクトの要件やチームのスキルセットに応じて、最適な組み合わせを選択することが成功への近道です。 まずは Express でプロトタイプを作成し、パフォーマンスが求められる部分で Fastify を試すといった段階的なアプローチもおすすめですね。
NestJS の柔軟なアーキテクチャを活かして、効率的で保守性の高いアプリケーション開発を実現していきましょう。
関連リンク
articleNestJS 2025 年の全体像:Express・Fastify・Serverless の使い分け早わかり
articleNestJS 監視運用:SLI/SLO とダッシュボード設計(Prometheus/Grafana/Loki)
articleNestJS クリーンアーキテクチャ:UseCase/Domain/Adapter を疎結合に保つ設計術
articleNestJS Decorator 速見表:Controller/Param/Custom Decorator の定型パターン
articleNestJS 最短セットアップ:Fastify + TypeScript + ESLint + Prettier を 10 分で
articleNestJS × ExpressAdapter vs FastifyAdapter:レイテンシ/スループットを実測比較
articlePrisma 読み書き分離設計:読み取りレプリカ/プロキシ/整合性モデルを整理
articleMermaid で日本語が潰れる問題を解決:フォント・エンコード・SVG 設定の勘所
articlePinia 2025 アップデート総まとめ:非互換ポイントと安全な移行チェックリスト
articleMCP サーバー 実装比較:Node.js/Python/Rust の速度・DX・コストをベンチマーク検証
articleLodash のツリーシェイクが効かない問題を解決:import 形態とバンドラ設定
articleOllama のインストール完全ガイド:macOS/Linux/Windows(WSL)対応手順
blogiPhone 17シリーズの発表!全モデルiPhone 16から進化したポイントを見やすく整理
blogGoogleストアから訂正案内!Pixel 10ポイント有効期限「1年」表示は誤りだった
blog【2025年8月】Googleストア「ストアポイント」は1年表記はミス?2年ルールとの整合性を検証
blogGoogleストアの注文キャンセルはなぜ起きる?Pixel 10購入前に知るべき注意点
blogPixcel 10シリーズの発表!全モデル Pixcel 9 から進化したポイントを見やすく整理
blogフロントエンドエンジニアの成長戦略:コーチングで最速スキルアップする方法
review今の自分に満足していますか?『持たざる者の逆襲 まだ何者でもない君へ』溝口勇児
reviewついに語られた業界の裏側!『フジテレビの正体』堀江貴文が描くテレビ局の本当の姿
review愛する勇気を持てば人生が変わる!『幸せになる勇気』岸見一郎・古賀史健のアドラー実践編で真の幸福を手に入れる
review週末を変えれば年収も変わる!『世界の一流は「休日」に何をしているのか』越川慎司の一流週末メソッド
review新しい自分に会いに行こう!『自分の変え方』村岡大樹の認知科学コーチングで人生リセット
review科学革命から AI 時代へ!『サピエンス全史 下巻』ユヴァル・ノア・ハラリが予見する人類の未来