BFFパターン(Backend for Frontend)

英語名 Backend for Frontend (BFF)
読み方 バックエンド フォー フロントエンド
難易度
所要時間 設計・実装に1〜2週間
提唱者 サム・ニューマン(SoundCloud在籍時に提唱)
目次

ひとことで言うと
#

モバイルアプリ、Webアプリ、サードパーティなど、クライアントの種類ごとに専用のバックエンド(BFF)を設けるパターン。汎用的な1つのAPIですべてのクライアントに対応するのではなく、各フロントエンドに最適化されたAPIを提供する。

押さえておきたい用語
#

押さえておきたい用語
BFF(Backend for Frontend)
フロントエンドの種類(Web、モバイル等)ごとに設ける専用のバックエンドサーバー。API翻訳層として機能する。
API集約(API Aggregation)
複数のマイクロサービスからデータを取得し、1つのレスポンスにまとめて返すこと。BFFの主要な役割の一つ。
オーバーフェッチング
クライアントが必要としない余分なデータまでAPIが返してしまう問題を指す。通信量とパース時間の無駄が生じる。
アンダーフェッチング
1回のAPI呼び出しでは足りず、複数回のリクエストが必要になる問題である。画面表示の遅延を招く。
API翻訳層
下流サービスのレスポンスをフロントエンドが使いやすい形に変換するレイヤー。BFFの本質的な役割。

BFFパターンの全体像
#

判断→責務定義→クライアント別設計→オーナーシップ決定の4ステップ
導入判断クライアント種類とAPI要件の差異を分析する責務定義集約・整形のみ担当ビジネスロジックは下流サービスに任せる個別設計Web/モバイル/外部それぞれの画面構成に合わせたAPIを設計オーナーシップフロントエンドチームがBFFを所有し自律的に変更する各フロントエンドに最適なAPIを提供する
BFFパターンの導入フロー
1
導入判断
クライアント要件の差異を分析
2
責務定義
集約・整形に限定する
3
個別設計
クライアント別にBFFを設計
4
オーナーシップ
FEチームが自律運用

こんな悩みに効く
#

  • モバイルアプリに不要なデータまでAPIが返していて、通信量が無駄に多い
  • Webとモバイルで必要なデータが異なるのに、1つのAPIで無理に対応している
  • フロントエンドの変更のたびにバックエンドAPIの修正が必要になる

基本の使い方
#

ステップ1: BFFが必要かどうかを判断する

BFFはすべてのプロジェクトに必要なわけではない。導入すべき状況を見極める。

  • BFFが有効: クライアントが複数種類(Web、モバイル、IoT)あり、それぞれ必要なデータや画面構成が大きく異なる
  • BFF不要: クライアントが1種類のみ、またはクライアント間のAPI要件がほぼ同じ
  • 代替手段: GraphQLで各クライアントが必要なデータだけ取得する方式も検討

ポイント: クライアントが1種類なら、BFFは過剰設計。シンプルなAPIで十分。

ステップ2: BFFの責務を明確にする

BFFが何をして、何をしないかを定義する。

  • BFFの責務: レスポンスの集約・整形、クライアント固有の認証、フロントエンド用のデータ変換
  • BFFに置かないもの: ビジネスロジック、データバリデーション、永続化処理
  • BFFは「フロントエンドのためのAPI翻訳層」であり、ビジネスロジックは下流のサービスに任せる

ポイント: BFFにビジネスロジックを入れると、ロジックの重複やBFF肥大化を招く。薄く保つこと。

ステップ3: クライアントごとにBFFを設計する

各クライアントの画面構成とデータ要件に合わせてBFFを設計する。

  • Web BFF: ページ単位で必要なデータを一括取得するエンドポイント
  • Mobile BFF: 帯域を考慮して最小限のデータを返す。ページネーションを積極的に活用
  • Third-party BFF: 安定したバージョニングとレート制限を備えた公開API

ポイント: 1つのBFFが複数クライアントを担当しない。そうするとBFFを導入した意味がなくなる。

ステップ4: BFFのオーナーシップを決める

BFFを誰が開発・保守するかを明確にする。

  • フロントエンドチームがBFFも開発する(推奨)。UIの要件変更に即座に対応できる
  • バックエンドチームに依頼する運用だと、コミュニケーションコストが発生する
  • BFFの技術スタックはフロントエンドチームが扱いやすいもの(Node.js等)を選ぶと良い

ポイント: **「UIを知っている人がBFFを書く」**のが、最も効率的な開発体制。

具体例
#

例1:旅行予約サービスでBFF分離によりモバイルのレスポンスサイズを87%削減する

状況: 旅行予約サービスの汎用API。Webの検索結果画面は詳細情報(写真10枚、口コミ5件)を表示、モバイルは一覧性重視(写真1枚、星評価のみ)。1つのAPIですべて返しており、モバイルで不要なデータを大量に送信していた。

BFF分離:

  • Web BFF (/web-bff/search): ホテル情報+写真10枚+口コミ5件+周辺施設 → 1レスポンス約15KB
  • Mobile BFF (/mobile-bff/search): ホテル名+写真1枚+星評価+料金 → 1レスポンス約2KB
  • 両BFFとも下流の同じマイクロサービス(ホテルサービス、口コミサービス)を呼び出す

モバイルアプリのレスポンスサイズが87%削減(15KB→2KB)。ページ読み込み速度が1.8秒→0.5秒に改善し、フロントエンドチームがBFFを自由に変更でき、バックエンドへの依頼待ちがゼロになった。

例2:EC企業がBFF導入でフロントエンド開発のリードタイムを60%短縮する

状況: Webとモバイルアプリが同じ汎用APIを使用。商品詳細ページの改修で、フロントエンドチームがバックエンドチームにAPI変更を依頼 → レビュー → 実装 → デプロイ待ちで平均10日。

施策:

  1. Node.js(TypeScript)でWeb BFFとMobile BFFを構築
  2. 各BFFのオーナーシップをフロントエンドチーム(各3名)に移管
  3. BFFは集約・整形のみ。価格計算や在庫チェックは下流サービスが担当

BFF導入の最大の効果は「待ち時間の解消」だった。フロントエンドの機能改修リードタイムが平均10日→4日に短縮され、バックエンドチームもAPIの汎用性を気にせずドメインロジックに集中できるようになった。

例3:IoTプラットフォームが3種類のBFFでデバイス・ダッシュボード・パートナーAPIを分離する

状況: IoTプラットフォーム。デバイス(数バイトの軽量JSON)、管理ダッシュボード(グラフ描画用の集計データ)、パートナーAPI(安定したバージョニング付き)の3クライアントが同一APIを共有。

BFF設計:

  • Device BFF: レスポンス100バイト以下。プロトコルバッファ対応。レイテンシ50ms以下
  • Dashboard BFF: 時系列データを1時間・1日・1週間単位で集計して返す
  • Partner BFF: REST + OpenAPI。バージョニングとレート制限(1000 req/min)付き

デバイスのバッテリー消費が23%改善(通信データ量削減による)。ダッシュボードの初期表示は4.2秒→1.1秒に改善し、パートナーからのAPI関連問い合わせも月30件→5件に減少した。

やりがちな失敗パターン
#

  1. BFFにビジネスロジックを入れてしまう — 注文バリデーションや価格計算をBFFに書くと、WebとモバイルのBFFでロジック重複が発生する。ビジネスロジックは下流サービスに集約する
  2. BFFが単なるプロキシになる — バックエンドのレスポンスをそのまま転送するだけならBFFの意味がない。データの集約・整形という価値を提供すること
  3. BFFの数を増やしすぎる — クライアント種類が増えるたびにBFFを増やすと保守が大変。本当にAPI要件が異なるクライアントだけにBFFを設ける
  4. BFFのオーナーシップが曖昧 — フロントエンドとバックエンドの両方が「相手の仕事」と思い、誰も面倒を見ない。BFFのオーナーを明確に定め、PRのアサインルールまで決める

まとめ
#

BFFパターンは、複数の異なるフロントエンドに対して最適なAPIを提供するための設計パターン。汎用APIの 「誰にとっても微妙」 な問題を解決し、各クライアントに必要十分なデータを効率的に届ける。BFFは薄く保ち、ビジネスロジックは下流に任せ、フロントエンドチームがオーナーシップを持つのが成功の方程式だ。