BFF (Backend for Frontend)
フロントエンドごとに専用のバックエンドを用意し、クライアントに最適化された API を提供するパターン
アーキテクチャAPI
BFF とは
BFF (Backend for Frontend) は、フロントエンドごとに専用のバックエンドを用意し、クライアントに最適化された API を提供するパターンである。Sam Newman が提唱。詳細は「BFF パターン」を参照。
なぜ必要か
❌ 汎用 API:
モバイル: /api/users/123 → 50 フィールド返却 (大半は不要)
Web: /api/users/123 → 50 フィールド返却 (別のフィールドが不要)
✅ BFF:
モバイル → Mobile BFF → { name, avatar } (必要最小限)
Web → Web BFF → { name, email, orders } (Web に最適化)
アーキテクチャ
モバイルアプリ → Mobile BFF (Lambda) → マイクロサービス群
Web アプリ → Web BFF (Lambda) → マイクロサービス群
管理画面 → Admin BFF (Lambda) → マイクロサービス群
BFF vs 汎用 API vs GraphQL
| 観点 | 汎用 API | BFF | GraphQL |
|---|---|---|---|
| Over-fetching | 発生する | 解決 | 解決 |
| クライアント最適化 | ❌ | ✅ | ✅ |
| バックエンド数 | 1 | クライアント数分 | 1 |
| 複雑さ | 低い | 中 | 中〜高 |
Lambda での BFF
// Mobile BFF: モバイルに最適化されたレスポンス
export const mobileHandler = async (event: APIGatewayProxyEventV2) => {
const userId = event.pathParameters?.id;
const [user, orders] = await Promise.all([
userService.get(userId!),
orderService.getRecent(userId!, 3), // モバイルは直近 3 件のみ
]);
return {
statusCode: 200,
body: JSON.stringify({
name: user.name,
avatar: user.avatar,
recentOrders: orders.map(o => ({ id: o.id, total: o.total })),
}),
};
};
BFF の注意点
| 注意点 | 対策 |
|---|---|
| BFF の肥大化 | ビジネスロジックを BFF に入れない |
| 重複コード | 共通ロジックをライブラリに抽出 |
| BFF の数が増える | GraphQL で代替を検討 |
いつ BFF を使うか
| ケース | 推奨 |
|---|---|
| モバイル + Web で異なるデータが必要 | ✅ BFF |
| 単一のフロントエンド | ❌ 汎用 API で十分 |
| クライアントが柔軟にデータを選びたい | GraphQL |
より深く学ぶには関連書籍が役立つ。