はじめに
GraphQL フェデレーションにより、各マイクロサービスが サブグラフを公開できるようになり、ルーターはそれを 統合スーパーグラフに自動的に構成します。フロントエンドでは、すべてのサービスからデータをクエリするために 1 つのエンドポイントのみが必要です。

1. 問題: 複数の GraphQL エンドポイント
❌ Mỗi service có GraphQL endpoint riêng:
Frontend → product.api.com/graphql (Product schema)
Frontend → user.api.com/graphql (User schema)
Frontend → order.api.com/graphql (Order schema)
→ Frontend phải biết endpoint nào chứa data gì
→ Không thể query cross-service trong 1 request
→ Ví dụ: Order + Product + User = 3 requests
2. GraphQL フェデレーション アーキテクチャ
✅ Unified Supergraph:
┌─────────────┐
│ Frontend │
│ 1 endpoint │
└──────┬──────┘
│
▼
┌──────────────────────┐
│ Apollo Router │
│ (Supergraph) │
│ gateway.api.com │
└──┬────────┬────────┬─┘
│ │ │
▼ ▼ ▼
┌──────┐ ┌──────┐ ┌──────┐
│Product│ │ User │ │Order │
│Subgra│ │Subgra│ │Subgra│
│ ph │ │ ph │ │ ph │
└──────┘ └──────┘ └──────┘
1 query → Router splits → Subgraphs → Router merges → 1 response
3. サブグラフの定義
3.1 製品サブグラフ
# Product Service subgraph
type Product @key(fields: "id") {
id: ID!
name: String!
price: Float!
description: String
category: Category!
}
type Category {
id: ID!
name: String!
}
type Query {
product(id: ID!): Product
products(limit: Int, offset: Int): [Product!]!
}
3.2 サブグラフの確認 (製品の拡張)
# Review Service subgraph — extends Product
type Product @key(fields: "id") {
id: ID!
reviews: [Review!]!
averageRating: Float
}
type Review {
id: ID!
rating: Int!
comment: String
author: User!
}
type Query {
reviews(productId: ID!): [Review!]!
}
3.3 フェデレーションクエリ
# Frontend query — Router handles cross-service resolution
query ProductPage($id: ID!) {
product(id: $id) {
id # → Product Subgraph
name # → Product Subgraph
price # → Product Subgraph
reviews { # → Review Subgraph
rating
comment
author { # → User Subgraph
name
avatar
}
}
averageRating # → Review Subgraph
}
}
自動ルーター:
- 製品サブグラフのクエリ → 製品データの取得
- レビュー サブグラフをクエリ → レビューを取得 (product.id を使用)
- ユーザー サブグラフをクエリ → 著者情報を取得 (review.author.id を使用)
- すべて結合 → 1 つの応答を返す
4. スキーマステッチングとフェデレーション
| スキーマの結合 | 連盟 | |
|---|---|---|
| 所有権 | ゲートウェイがスキーマを所有 | サービス独自のスキーマ |
| カップリング | 高 (ゲートウェイはサービスを認識しています) | 低 (サービス自体が宣言) |
| スケーラビリティ | ゲートウェイのボトルネック | 分散 |
| 進化 | ハード(センターチェンジ) | 簡単 (サービスレベル) |
| 評決 | ❌ レガシー | ✅ おすすめ |
5. パフォーマンスに関する考慮事項
5.1 クエリプランの最適化
Router tạo query plan tối ưu:
─ Parallel: Product + User subgraphs (independent)
─ Sequential: Reviews → after Product (needs product.id)
5.2 データローダーのパターン
// Trong Review Subgraph, batch user lookups
const userLoader = new DataLoader(async (userIds) => {
const users = await userService.getUsers(userIds);
return userIds.map(id => users.find(u => u.id === id));
});
// Resolve author field
Review: {
author: (review) => userLoader.load(review.authorId)
}
5.3 キャッシュ
Persisted Queries: Client gửi query hash thay vì full query
Automatic Persisted Queries (APQ): Router cache query plans
CDN caching: @cacheControl directive
6. フェデレーションをいつ使用するか?
✅ Dùng khi:
- Nhiều microservices cần unified GraphQL API
- Frontend teams muốn 1 endpoint
- Complex, nested data relationships
- Multiple frontend clients
❌ Không cần khi:
- Chỉ có 1-2 services (đơn giản quá)
- REST đã đủ tốt
- Team chưa quen GraphQL
- Performance-critical (thêm latency qua Router)
概要
- フェデレーション = 各サービス独自のサブグラフ、ルーターがスーパーグラフを構成
@keyサブグラフ間のエンティティ参照のディレクティブ- ルーターは自動的にクエリを分割、解決、マージします
- DataLoader パターンにより N+1 問題を回避
- 複数のサービスに 統合された GraphQL API が必要な場合に使用します