express vs fastify 徹底比較

express の詳細fastify の詳細
AI生成コンテンツ

この記事はAIによって生成されました。内容の正確性は保証されません。最新の情報は公式ドキュメントをご確認ください。

Express vs Fastify — Node.js Webフレームワーク徹底比較

1. 結論

新規プロジェクトでパフォーマンスと型安全性を重視するなら Fastify を選びましょう。 既存の膨大なミドルウェア資産を活用したい場合や、チームの学習コストを最小限にしたい場合は Express が依然として堅実な選択です。どちらも本番運用に十分耐えうるフレームワークですが、設計思想が異なるため、プロジェクトの要件に合わせて選ぶことが重要です。


2. 比較表

項目ExpressFastify
npm 週間DL数約 3,500万+約 350万+
GitHub Stars約 66k+約 33k+
最新メジャーバージョンv4(v5 beta)v5
バンドルサイズ(node_modules)約 210 KB約 2.2 MB(プラグイン込み)
ベンチマーク(req/sec)約 15,000約 50,000+
TypeScript 対応@types/express で外部型定義コア同梱の型定義(ファーストクラス)
スキーマバリデーション外部ライブラリが必要JSON Schema ベースで組み込み
ロギング外部ライブラリが必要Pino が組み込み
プラグインエコシステム非常に豊富(数千)成長中(公式プラグイン 200+)
学習コスト低いやや高い(プラグインシステムの理解が必要)
設計思想ミニマル・非主張的プラグイン駆動・カプセル化
HTTP/2 対応外部モジュールが必要ネイティブサポート
ライセンスMITMIT

3. それぞれの強み

Express の強み

  • 圧倒的なエコシステム: 10年以上の歴史があり、ほぼあらゆるユースケースに対応するミドルウェアが存在します。Passport.js、multer、cors など、定番ライブラリとの統合がスムーズです。
  • 学習コストの低さ: req / res / next というシンプルなミドルウェアモデルは、Node.js 初学者でも直感的に理解できます。ドキュメント、書籍、チュートリアルの量も圧倒的です。
  • 柔軟性: フレームワーク側が構造を強制しないため、小さな API サーバーからモノリシックなアプリケーションまで自由に設計できます。
  • 採用実績: Netflix、Uber、IBM など大規模企業での採用実績があり、長期的なメンテナンスへの信頼感があります。

Fastify の強み

  • 圧倒的なパフォーマンス: 内部で find-my-way(Radix Tree ベースのルーター)と高速な JSON シリアライゼーションを採用しており、Express の約 3〜5 倍のスループットを実現します。
  • ファーストクラスの TypeScript サポート: ジェネリクスを活用した型定義がコアに同梱されており、リクエスト・レスポンスの型を厳密に定義できます。
  • JSON Schema によるバリデーション & シリアライゼーション: ルート定義にスキーマを宣言するだけで、入力バリデーションとレスポンスのシリアライゼーション高速化を同時に実現します。
  • プラグインアーキテクチャ: カプセル化されたプラグインシステムにより、依存関係の分離とテスタビリティが向上します。fastify-plugin@fastify/autoload などの仕組みが強力です。
  • 組み込みロギング: 高速ロガー Pino が統合されており、構造化ログを追加設定なしで利用できます。

4. コード例で比較

ユーザー作成 API(POST /users)を実装する

Express の場合

// express-app.ts
import express, { Request, Response, NextFunction } from "express";

interface CreateUserBody {
  name: string;
  email: string;
  age: number;
}

interface User extends CreateUserBody {
  id: number;
}

const app = express();
app.use(express.json());

// ── バリデーションミドルウェア(手動実装) ──
function validateCreateUser(req: Request, res: Response, next: NextFunction): void {
  const { name, email, age } = req.body as Partial<CreateUserBody>;

  const errors: string[] = [];
  if (typeof name !== "string" || name.length < 1) {
    errors.push("name は1文字以上の文字列が必要です");
  }
  if (typeof email !== "string" || !email.includes("@")) {
    errors.push("email は有効なメールアドレスが必要です");
  }
  if (typeof age !== "number" || age < 0 || age > 150) {
    errors.push("age は 0〜150 の数値が必要です");
  }

  if (errors.length > 0) {
    res.status(400).json({ errors });
    return;
  }
  next();
}

// ── ルート定義 ──
app.post("/users", validateCreateUser, (req: Request, res: Response) => {
  const { name, email, age } = req.body as CreateUserBody;

  const newUser: User = {
    id: Math.floor(Math.random() * 10000),
    name,
    email,
    age,
  };

  res.status(201).json(newUser);
});

// ── エラーハンドリング ──
app.use((err: Error, _req: Request, res: Response, _next: NextFunction) => {
  console.error(err.stack);
  res.status(500).json({ error: "Internal Server Error" });
});

app.listen(3000, () => {
  console.log("Express server running on http://localhost:3000");
});

Fastify の場合

// fastify-app.ts
import Fastify, { FastifyRequest, FastifyReply } from "fastify";

interface CreateUserBody {
  name: string;
  email: string;
  age: number;
}

interface User extends CreateUserBody {
  id: number;
}

const app = Fastify({
  logger: true, // Pino ロガーが自動で有効化
});

// ── ルート定義(スキーマバリデーション込み) ──
app.post<{ Body: CreateUserBody; Reply: User }>(
  "/users",
  {
    schema: {
      body: {
        type: "object",
        required: ["name", "email", "age"],
        properties: {
          name: { type: "string", minLength: 1 },
          email: { type: "string", format: "email" },
          age: { type: "integer", minimum: 0, maximum: 150 },
        },
        additionalProperties: false,
      },
      response: {
        201: {
          type: "object",
          properties: {
            id: { type: "integer" },
            name: { type: "string" },
            email: { type: "string" },
            age: { type: "integer" },
          },
        },
      },
    },
  },
  async (request: FastifyRequest<{ Body: CreateUserBody }>, reply: FastifyReply) => {
    const { name, email, age } = request.body;

    const newUser: User = {
      id: Math.floor(Math.random() * 10000),
      name,
      email,
      age,
    };

    return reply.status(201).send(newUser);
  }
);

// ── サーバー起動 ──
app.listen({ port: 3000 }, (err) => {
  if (err) {
    app.log.error(err);
    process.exit(1);
  }
});

コード例から読み取れる違い

観点ExpressFastify
バリデーションミドルウェアとして手動実装(または zod / joi を別途導入)JSON Schema をルート定義に宣言するだけ
型の連携req.body の型は any ベースでキャストが必要ジェネリクスで Body / Reply を型パラメータとして渡せる
ロギングconsole.log か外部ライブラリを別途設定logger: true だけで構造化ログが出力される
レスポンスシリアライゼーションJSON.stringify がそのまま使われるレスポンススキーマから高速シリアライザが自動生成される
コード量バリデーション込みでやや多いスキーマ定義は増えるが、ロジック部分は簡潔

5. どちらを選ぶべきか — ユースケース別の推奨

Express を選ぶべきケース

ユースケース理由
プロトタイプ・MVP の高速開発最小限のコードで動くものを作れる。情報量が多く詰まりにくい
既存の Express アプリの保守・拡張無理に移行するメリットは薄い。段階的な改善が現実的
チームに Node.js 初心者が多いミドルウェアモデルはシンプルで教育コストが低い
特定のミドルウェアに依存しているPassport.js、express-session など Express 専用のエコシステムが必要な場合
SSR フレームワークとの統合Next.js のカスタムサーバーなど、Express 前提のツールが多い

Fastify を選ぶべきケース

ユースケース理由
高トラフィックな API サーバーベンチマークで 3〜5 倍のスループット差は、インフラコストに直結する
TypeScript ファーストの新規プロジェクト型定義がコアに統合されており、DX が優れている
マイクロサービスアーキテクチャプラグインのカプセル化により、サービス境界の分離が自然にできる
OpenAPI / Swagger ドキュメント自動生成@fastify/swagger でスキーマからドキュメントを自動生成できる
厳密な入出力バリデーションが必要JSON Schema ベースのバリデーションが組み込みで、セキュリティ面でも有利
構造化ログ・可観測性を重視Pino 統合により、JSON ログの出力が標準で行える

どちらでもよいケース

  • 小〜中規模の社内ツール API
  • BFF(Backend for Frontend)レイヤー
  • 学習目的の個人プロジェクト

これらの場合は、チームの習熟度や好みで選んで問題ありません。


6. まとめ

Express  = 「枯れた安定」 × 「巨大なエコシステム」 × 「低い学習コスト」
Fastify  = 「高パフォーマンス」 × 「型安全性」 × 「モダンな設計思想」

Express は Node.js Web フレームワークのデファクトスタンダードとして、今なお多くのプロジェクトで活躍しています。一方で Fastify は、Express の課題(パフォーマンス、型安全性、構造化)を正面から解決するために設計されたフレームワークです。

2025年時点での筆者の所感としては、新規の API サーバーを TypeScript で構築するなら Fastify を第一候補にすることをおすすめします。 ただし、Express のエコシステムの厚みは唯一無二であり、「Express だから悪い」ということは決してありません。

最終的には、チームのスキルセット・プロジェクトの寿命・パフォーマンス要件の 3 軸で判断するのが最も合理的です。どちらを選んでも、Node.js の Web 開発を支える優れたフレームワークであることに変わりはありません。