第10章: おわりに ─ 4 原理回収 + 2026 構成パターン + v12 ロードマップ
第0章「はじめに」で本シリーズは「この機能、自前で書いてるけど NestJS の何かと被ってないか?」という疑念から始まった。第1部で内部構造を、第2部で標準モジュール 18 種と再発明 TOP 10 を、第3部で性能・メモリ効率を、第4部で 15 のアンチパターンを見てきた。
表面的にはバラバラな話に見えただろうが、根は 4 つの原理しかなかった。本章で回収する。さらに 2026 構成パターンと v12 ロードマップで未来を見渡す。
原理1: DI コンテナを信頼する
各章での現出
- 第1章:
DependenciesScanner → InstanceLoaderの 2 段、Provider Scope(DEFAULT / REQUEST / TRANSIENT)、Custom Provider 4 種、forwardRefの解決メカニズム、ModuleRef - 第4章:Module DAG、Dynamic Module、v11 の Module 解決アルゴリズム刷新(オブジェクト参照ベース)
- 第6章:再発明 TOP 10 の半数は「DI で取れるものを
newしていた」 - 第7章:REQUEST 伝染と Durable Providers
- 第9章:アンチパターン #4(forwardRef で隠蔽)/ #11(DI で取れるものを new)/ #15(main.ts 肥大化)
回収のフレーズ
「自分で new していないか」「DI で取れるものを取っているか」が出発点。NestJS の DI コンテナはあなたの想像より賢い。Object.create() で循環依存も解決し、Custom Provider 4 種で柔軟に依存を組める。DI を信頼するほど、テストが楽になり、リファクタリングが安全になる。
原理2: Decorator は「メタデータ宣言 + 実行時 hook」の二層
各章での現出
- 第2章(中核):
Reflect.metadataの格納場所、__decorateヘルパー、design:paramtypes、Stage 3 を採用しない理由、Custom Decorator 3 パターン、DiscoveryService - 第5章:18 モジュールの多くが Decorator + 起動時収集パターン(
@OnEvent/@Cron/@CommandHandler) - 第6章:Custom Decorator で再発明領域を埋める(
@MurLock/@UseResilience)
回収のフレーズ
@Injectable() の本質は「TypeScript に design:paramtypes を出させること」。これが分かれば、Decorator は怖くない。「特定 Decorator が付いた全 method を集める」自前フレームワーク的拡張も DiscoveryService + MetadataScanner で書ける。NestJS が標準で提供している多くの「魔法」は、この仕組みで動いている。
原理3: リクエスト境界の「層」を正しく使い分ける
各章での現出
- 第3章(中核):完全な順序(Middleware → Guard → Interceptor (before) → Pipe → Handler → Interceptor (after) → Filter)、各層の責務、global / controller / route スコープ、
APP_GUARDtoken の重要性、ExecutionContext - 第9章:アンチパターン #5-9, #12-14 が層の責務違反
回収のフレーズ
「どこで何をすべきか」を間違えると、アンチパターン 15 のうち 8 個が生まれる。Middleware / Guard / Interceptor / Pipe / Handler / Filter はそれぞれ違う仕事をする。Interceptor で DB を引かない、Pipe で外部 API を叩かない、Service 内に try-catch を散らかさない ─ これらすべて、層の責務を正しく理解すれば自然に避けられる。
原理4: メモリ効率は DI スコープ × ストリーム × Logger 設計に集約
各章での現出
- 第7章(中核):REQUEST 伝染と p99 レイテンシ低下、Durable Providers / nestjs-cls の使い分け
- 第8章:class-validator vs typia 15,000 倍差、Pino + AsyncLocalStorage、Cache Stampede 対策
- 第9章:アンチパターン #1-3, #10 が DI スコープに、#3 が Logger に集約
回収のフレーズ
アンチパターン 15 のうち 4 個は DI スコープ、1 個は Logger に直接関わる。表面的な「動いている」と本番運用での「速い」は別物。REQUEST 伝染を見抜き、Logger を Pino + ALS に切り替え、Cache に TTL Jitter を入れる ─ これだけで多くのプロダクションの p99 が改善する。
4 原理が章をまたいで効く ─ 全体マップ
graph TB
subgraph 4 Principles
P1[原理1<br/>DI コンテナを信頼]
P2[原理2<br/>Decorator 二層構造]
P3[原理3<br/>リクエスト 6 層]
P4[原理4<br/>scope × stream × logger]
end
subgraph Part 1 / 内部構造
C1[第1章 DI コンテナ]
C2[第2章 Decorator]
C3[第3章 リクエストライフサイクル]
C4[第4章 Module + v11]
end
subgraph Part 2 / 棚卸し
C5[第5章 18 モジュール]
C6[第6章 再発明 TOP 10]
end
subgraph Part 3 / 性能
C7[第7章 DI scope]
C8[第8章 Validation/Logger/Cache]
end
subgraph Part 4 / 実践
C9[第9章 15 アンチパターン]
end
P1 -.-> C1
P1 -.-> C4
P1 -.-> C6
P1 -.-> C9
P2 -.-> C2
P2 -.-> C5
P3 -.-> C3
P3 -.-> C9
P4 -.-> C7
P4 -.-> C8
P4 -.-> C9
「同じ式が全章に効く」 ─ 第0章で予告した通り、4 原理が全章を貫いた。
2026 構成パターン ─ NestJS の現代的使い方
NestJS で書く側のロードマップとして、2026 年現在の代表的構成パターンを整理する。
1. Modular Monolith(モジュール式モノリス)
「いきなり microservices にしない」が 2025-26 年の主流。NestJS の Module 境界がそのまま将来の microservice 化の seam(縫い目)になる。
apps/
├── api/ ← 1 つの NestJS アプリ
│ └── src/
│ ├── auth/ ← 将来 microservice 化候補
│ ├── billing/ ← 将来 microservice 化候補
│ ├── notifications/
│ └── ...
規模が小さいうちは Module 境界だけ綺麗に保つ、規模が大きくなったら一部を @nestjs/microservices で別プロセスに切り出す。最初から microservices で始めるより運用コストが圧倒的に低い。
2. CQRS / Saga(複雑ドメイン向け)
@nestjs/cqrs で Command / Query / Event を分離する DDD 系パターン。
// Command(書き込み)
class CreateUserCommand { /* ... */ }
@CommandHandler(CreateUserCommand)
class CreateUserHandler { /* mutate */ }
// Query(読み取り)
class GetUserQuery { /* ... */ }
@QueryHandler(GetUserQuery)
class GetUserHandler { /* read */ }
// Saga(複数 event の連鎖)
@Injectable()
class UserSagas {
@Saga()
signedUp = (events$) =>
events$.pipe(
ofType(UserCreatedEvent),
map(() => new SendWelcomeEmailCommand()),
);
}
注意:過剰適用しない。CRUD レベルまで Command/Query 分離すると保守コストが爆発する。ドメインが本当に複雑な領域にだけ。
3. LLM / Agent Backend
2025-26 年の急成長領域。NestJS は LLM / AI Agent のバックエンドとしても採用が増えている。
Server-Sent Events(SSE)で LLM ストリーミング
@Sse('chat/:id/stream')
streamChat(@Param('id') chatId: string): Observable<MessageEvent> {
return new Observable(subscriber => {
const abortController = new AbortController();
this.llmService.streamCompletion(chatId, {
signal: abortController.signal, // ← クライアント切断で課金停止
}).subscribe({
next: (chunk) => subscriber.next({ data: chunk }),
complete: () => subscriber.complete(),
});
return () => abortController.abort(); // teardown
});
}
重要:
- nginx の
X-Accel-Buffering: noで proxy buffering を切る - AbortSignal でクライアント切断を LLM API に伝搬(課金停止)
- 長時間接続の管理(タイムアウト・再接続)
MCP Server
Model Context Protocol サーバを NestJS で書ける時代に。@nestjs-mcp/server や @rekog/mcp-nest が登場。
@McpServer({ name: 'cats-api', version: '1.0.0' })
export class CatsMcpServer {
@McpTool({ description: 'Find cats by breed' })
async findCats(@McpInput() input: { breed: string }) {
return await this.svc.findByBreed(input.breed);
}
}
Decorator + Discovery の組み合わせで MCP tool を宣言できる ─ NestJS の哲学に合っている。
4. Graceful Shutdown × Kubernetes
K8s で動かすときの標準実装。
async function bootstrap() {
const app = await NestFactory.create(AppModule, { bufferLogs: true });
app.useLogger(app.get(Logger));
app.enableShutdownHooks(); // ← 必須
await app.listen(3000);
}
@Injectable()
export class HealthService implements BeforeApplicationShutdown {
private isShuttingDown = false;
async beforeApplicationShutdown() {
this.isShuttingDown = true;
// K8s の readiness probe が 503 を返すように
// → K8s は新規リクエストを送らなくなる
// → in-flight は処理完了まで待つ
}
isReady() { return !this.isShuttingDown; }
}
// /health/readiness で参照
@Get('readiness')
readiness() {
if (!this.healthService.isReady()) {
throw new ServiceUnavailableException();
}
return this.health.check([/* ... */]);
}
K8s の terminationGracePeriodSeconds(デフォルト 30 秒)と整合させる。
5. PM2 / Cluster は K8s 環境では不要
歴史的に NestJS + PM2 cluster mode が標準だったが、K8s 環境では 1 pod = 1 process が現代的。K8s 自身が cluster の役割を果たす。
| 環境 | プロセス管理 |
|---|---|
| 旧オンプレ / VM | PM2 cluster mode(CPU コア数だけ) |
| K8s | 1 pod = 1 process、HPA で水平スケール |
v12 ロードマップ(参考、Q3 2026 予定)
NestJS v12 の方向(PR #16391 から推測される範囲):
| 項目 | 内容 |
|---|---|
| 完全 ESM 移行 | CommonJS から ESM。Node.js の require(esm) 対応が決め手 |
| Test:Jest → Vitest | Vitest の速度・ESM 親和性 |
| Lint:ESLint → oxlint | Rust 製で高速 |
| Bundle:Webpack → Rspack | 同じく高速化 |
| Standard Schema 対応 | @Body() / @Query() / @Param() で Zod / Valibot / ArkType を直接使える |
| その他 | NATS v3 対応、Express の graceful shutdown 強化、WebSocket disconnect reason |
特に Standard Schema 対応は、第8章で扱った class-validator のパフォーマンス問題への正面回答になる可能性がある。
全章参考文献
NestJS 公式
- Documentation
- Migration Guide
- Request Lifecycle
- Lifecycle Events
- Provider Scopes
- Circular Dependency
- Module Reference
- Dynamic Modules
- Execution Context
- Discovery Service
- Lazy Loading
- Caching
- Task Scheduling
- Terminus
- Configuration
- Rate Limiting
- Events
- Queues
- Microservices
- GraphQL
- WebSockets
- Server-Sent Events
- Validation
- Exception Filters
- CQRS
- Performance
GitHub(公式 + コミュニティ)
- nestjs/nest releases
- v12 PR #16391
- issue #1735 (class-validator 置き換え)
- issue #8390 (class-transformer deprecation)
- issue #9541 (request-scope bubbling)
- iamolegga/nestjs-pino
- Papooch/nestjs-cls
- BenLorantfy/nestjs-zod
- ppetzold/nestjs-paginate
- SocketSomeone/nestjs-resilience
- felanios/murlock
Trilon / NestJS チームブログ
深掘り技術記事
- Why You Should Avoid Using Request-scoped Injection in NestJS
- Samchon: typia 15000x faster validator
- Don’t use class-validator in NestJS
- Production Logging in NestJS with Pino
- Performant Multi-tenant SaaS with Durable Providers
- Avoiding Circular Dependencies in NestJS
- NestJS Anti-patterns That Ship
- 7 DI Antipatterns in NestJS
- Implementing Contextual Logging in NestJS using AsyncStorage
- Cache Stampede Prevention
LLM / Agent / MCP
V8 / Node.js
最後に
NestJS は強い意見を持ったフレームワークだ。Spring 系 Java、ASP.NET Core、Angular 由来の DI とデコレータ、RxJS 思想 ─ これらを正しく理解しないと、表層だけで「動かす」ことはできても、本番で 5 倍遅くなるコードを書いてしまう。
しかし、4 つの原理を理解しさえすれば、機能はいくつ増えても本質は変わらない:
- DI コンテナを信頼する ─ 自分で
newしていないか、DI で取れるものを取っているか - Decorator は二層構造 ─ メタデータ宣言 + 実行時 hook、
Reflect.metadataで動く - リクエスト境界の層を使い分ける ─ Middleware / Guard / Interceptor / Pipe / Handler / Filter の責務
- メモリ効率は scope × stream × logger ─ アンチパターン 15 のうち大半はここ
新しい機能(v11、v12、その先)が出るたびに「これは原理 1 の延長か、3 の延長か」と問えば、自然に位置付けられる。
最初の段階で第5章のチェックリストを月次でレビュー、第9章のアンチパターン 15 を四半期で点検、第6章の再発明 TOP 10 を新規開発のたびに参照 ─ この 3 つのリズムで、NestJS アプリケーションを成熟させていけるはずだ。
ここまで読んでいただき、ありがとうございました。本シリーズが、あなたの NestJS プロダクトを**「使い倒している」**状態へ引き上げる足場になれば幸いです。