Webとモバイルクライアント向けのAPIゲートウェイとBFF:トレードオフ
APIゲートウェイとBFF:それぞれのパターンがバージョニング、パフォーマンス、公開と内部エンドポイントの分離にどう影響するかを学びます。

問題:一つのバックエンド、多様なクライアント、変化する要件
よくある出発点はシンプルです:1つのバックエンドが一連のエンドポイントを公開し、Webアプリとモバイルアプリの両方がそれを呼び出します。機能追加、バグ修正、ルール適用の場所が一つで済むので効率的に感じられます。
しかし現実は違います。Web UIはしばしば密な画面、フィルタ、エクスポート、管理アクションを必要とします。モバイルは通常、項目数が少なく高速、オフライン対応フロー、バッテリーやデータ使用に配慮が必要です。機能が「同じ」でも、各クライアントに最適なAPIの形はめったに同一ではありません。
時間が経つとエンドポイントは変化します。Webチームが新しいテーブルビュー向けに余分なフィールドを追加し、モバイルは重いペイロードを削減して複数の呼び出しをまとめることを求めます。誰かが「iOS向けだけの」パラメータを追加します。別の人が内部の管理エンドポイントを「既にあったから」という理由で公開アプリで使います。かつてはきれいだった単一APIは、妥協の集合体に変わります。
リスクはすぐに現れます:
- 片方のクライアントが速く出すことで破壊的変更が起きる
- 大きなペイロードや多すぎる往復でアプリが遅くなる
- すべてのクライアントに対応しようとすることでバックエンドのコードが複雑化する
- 内部フィールドや管理アクションが誤って公開APIに漏れる
- "小さな変更" が古いクライアントには小さくないため、バージョニングがつらくなる
これはAPIゲートウェイ対BFFの議論の核心です。モバイルとWebが頼れる安定した公開APIを維持しつつ、各クライアントが自分のペースで進化できる余地をどう残すかがポイントです。
APIゲートウェイとBFF:それぞれ何か(何ではないか)
APIゲートウェイはAPIへの玄関口です。クライアントはゲートウェイに呼び出し、ゲートウェイは適切なバックエンドサービスにルーティングします。認証チェック、レート制限、リクエストログ、基本的なリクエスト整形など、あちこちで繰り返したくない共通の関心事を扱うことが多いです。
BFF(backend-for-frontend)は特定のクライアントやクライアント群(例えば「Web」「モバイル」)向けに作られた小さなバックエンドです。クライアントは自分のBFFを呼び、BFFが下位のサービスを呼びます。重要なのはフォーカスで、BFFはクライアントの言葉(画面やフロー、ペイロード)で話すことを許されます。コアサービスはより汎用のままでも構いません。
これらのパターンが何でないか:良いドメインサービスやきれいなデータモデルの代替ではありません。コアのサービス、データベース、ビジネスルールは真の信頼できる情報源であるべきです。ゲートウェイやBFFがビジネスロジックの巨大な塊になり、本当のバックエンドに変わってはいけません。
簡単な区別方法:
- ゲートウェイ:入口は一つ、共有関心事、ルーティングと保護
- BFF:クライアント固有のAPIでクライアント側の負担を減らし内部の複雑さを隠す
両者を組み合わせることもできます。一般的な構成は、公開エッジとしてゲートウェイを置き、その背後にWebとモバイル用の別々のBFFを置くパターンです。ゲートウェイは外側のセキュリティとトラフィック制御を担当し、各BFFがエンドポイントやレスポンスをクライアント向けに整形します。
リクエスト経路はどう変わるか
APIゲートウェイとBFFの最大の違いは、ルーティング、認証チェック、レスポンス整形といった「フロントドア」ロジックをどこに置くかです。
APIゲートウェイでは、クライアントは通常ひとつの共有エントリポイントに話しかけます。ゲートウェイは内部サービスにリクエストをフォワードし、トークン検証、レート制限、パスによるルーティングなどの基本処理を行います。
BFFでは、各クライアントタイプ(Web、iOS、Android)がそれぞれ専用のバックエンドを呼びます。そのBFFが内部サービスを呼び、クライアントの画面や制約に合わせたレスポンスを返します。
イメージしやすい経路の違い:
- APIゲートウェイ経路: クライアント -> ゲートウェイ -> サービス群 -> レスポンス
- BFF経路: クライアント -> BFF(web または mobile) -> サービス群 -> レスポンス
所有権もシフトすることが多いです。ゲートウェイは全チーム・全サービスに影響するためプラットフォームやインフラチームが所有することが一般的です。BFFはUIとリリースサイクルに追従するため、機能チームが所有することが多いです。
認証は一般にこう流れます:クライアントがトークンを送り、エッジ層(ゲートウェイかBFF)が検証するか認証サービスに渡し、下流にユーザーIDやロールを転送します。違いはクライアント固有のルールをどこで適用するかです。ゲートウェイではポリシーは一般的で一貫性がありますが、BFFではモバイル向けに小さなペイロードを返したり、複数のサービス呼び出しを1つにまとめたりといったクライアント固有の整形が可能です。
この整形がBFFの得意なところですが、展開や整合性を保つための運用対象が増えるという代償もあります。
公開APIと内部APIを安全に分ける
公開エンドポイントは、Webアプリ、モバイルアプリ、パートナー、サードパーティが到達できるすべてのAPIルートです。ネットワークやクライアントコードを制御できないので、デフォルトで敵対的に扱ってください。
内部エンドポイントはシステム内のサービス間トラフィック向けです。より速く変化させたり、より多くのコンテキストを想定したり、豊富なデータを露出できますが、公開インターネットから直接到達可能にしてはいけません。
APIゲートウェイがある場合、分離は物理的で分かりやすいことが多いです:公開されるのはゲートウェイだけで、ゲートウェイがどの外部ルートを公開するかを決めます。内部サービスAPIは表現力を保てますが、ゲートウェイが安全な小さな表面を強制します。
BFFパターンでは分離は製品境界に関するものになります。各クライアント(Web、iOS、Android)は自分のBFFにのみ話し、BFFが内部サービスを呼びます。BFFは3つのサービスを呼んで結果をマージし、クライアントが本当に必要とする単一のレスポンスを公開できます。
分離を安全にするために実用的な制御を追加してください:
- 各ルートごとの明確な認可:単なる「ログイン済み」スイッチではなくロールとスコープを使う
- 公開エンドポイントに対するユーザー、トークン、IPごとのレート制限
- ペイロードフィルタリング:クライアントに必要なものだけを返し、内部ID、デバッグ情報、管理専用フィールドを削除する
- 明確な許可リスト:どのエンドポイントが公開か、どれが内部専用か
例:モバイルアプリの「マイ注文」画面。BFFは /orders を注文ステータスと合計だけ返すようにし、内部の注文サービスは詳細な原価内訳や不正検知フラグを非公開にできます。
バージョニング:何が楽になり、何が難しくなるか
バージョニングの悩みは、Webとモバイルが異なる速度で動くときに現れます。Webチームは数時間でロールアウトやロールバックできますが、モバイルはアプリストア審査や更新しないユーザーの存在で数日〜数週間かかることがあります。このギャップはAPIゲートウェイとBFFの選択を実用的なものにします。
APIゲートウェイなら、フロントドアでバージョン管理できます(例:/v1/..., /v2/...)。説明やルーティングは簡単です。しかし、多くのクライアントやパートナー統合が古いバージョンに固執するとゲートウェイがバージョン博物館になりがちで、古いデータ形態を長期間サポートすることになり得ます。
BFFではバージョニングは「クライアントごと」になることが多いです。モバイルBFFは古い契約のままにして、Web BFFは速く動けます。これにより公開バージョンを永遠に維持する圧力が減りますが、管理すべき決定が増え、デプロイも増えます。
サービス内部でバージョニングすることも可能ですが、クライアント主導の変更をシステム深部に押し込むことになり、サービスロジックがクライアントバージョンごとに分岐して読みづらくなることがあります。
非互換変更を避けるのが最善です:オプションのフィールド追加、新しいエンドポイント追加、余分な入力フィールドの受け入れなど。破壊的変更にはフィールド名の変更、型の変更(文字列→数値)、エンドポイントの削除が含まれます。
廃止は計画的に行うのがベストです:
- 明確なサンセット日を設定し、早めに通知する
- 古いバージョンの利用状況を追跡する(ログ、メトリクス)
- まずクライアントを更新(特にモバイル)してから古いパスを削除する
- 古いバージョンをブロックする際には明確なエラーメッセージを返す
パフォーマンス:レイテンシ、ペイロードサイズ、呼び出し数
APIゲートウェイ対BFFのパフォーマンスは基本的にトレードオフです:システム内部での1つのホップが増える代わりに、クライアント側の遅いネットワーク往復を減らせるかどうかがポイントです。クライアントのネットワーク時間を減らせる設計がしばしば最速になります。
クライアントが多数の呼び出しを行う場合、BFFが有利です。Webやモバイルが5つのエンドポイントを呼んでデバイス側で結果を組み合わせる代わりに、BFFがサーバー側で取りに行き1つのレスポンスにまとめれば、モバイルでは特に総レイテンシが大幅に減ります。セルラーネットワークは各リクエストに遅延を追加するためです。
ゲートウェイやBFFから得られる一般的な性能向上:
- 集約:複数サービスのデータを一つにまとめる
- 賢いキャッシュ:エッジやBFFでのキャッシュ(読み取り重視の画面に有効)
- 小さなペイロード:画面が必要とするフィールドだけ返す
- 往復回数の削減:チャッティなクライアント動作を減らす
- 一貫した圧縮とタイムアウト:一箇所でデフォルトを強制する
ただし、レイヤーを追加するとCPU負荷や待ちが増えます。同じ集約ロジックをWebとモバイルで複製すると二重の作業が発生し、一貫性も失われます。汎用エンドポイントがすべての画面を満たそうとして必要以上に大きなレスポンスを返す「過取得」もよくある損失です。
モバイル事情はトレードオフをより厳しくします。ネットワークが不安定だとリトライやタイムアウトが普通になり、呼び出しが増えるほどバッテリーを消費します。コールドスタートも重要です:最初の画面が表示される前に複数のリクエストが必要ならユーザーは遅さを感じます。
実用的なルール:まずクライアント側のリクエスト数を減らすことを最優先にし、その後に追加ホップの最適化を行ってください。
設計を簡単に判定する方法
ある画面に順番に2〜3回以上の呼び出しが必要なら、集約を検討してください。レスポンスが大きく大部分が未使用であれば、エンドポイントを分けるかクライアント向けにBFFを使うことを検討してください。
運用:デプロイ、監視、スケーリング
APIゲートウェイとBFFの大きな運用上の問いは、どれだけ多くの稼働コンポーネントを運用・サポートする覚悟があるかです。ゲートウェイは多くのチームとクライアントにとって共有インフラになりがちです。BFFは小さなサービスですが、クライアントごとに1つずつ作るとデプロイ数やオンコールの負荷が増えます。
テストとリリースでは、ルーティング、認証、レート制限が主な要件ならゲートウェイの方が安全なことがあります。変更が集中しているため一つのミスで全体に影響します。BFFは変更の衝撃範囲を小さくします:Web専用の変更はWeb BFFにデプロイされ、モバイルには影響しません。代わりにパイプラインや稼働中のバージョンが増えます。
可観測性では、1つのユーザーリクエストがレイヤーを跨いで追跡できることが重要です。モバイルの1つの呼び出しが複数のバックエンド呼び出しを引き起こす場合、見通しがないとデバッグが難しくなります。
- 相関IDを使い、ゲートウェイ、BFF、バックエンドのログに渡す
- トレースを取得して時間を費やしている箇所(ゲートウェイ、BFF、下流サービス)を特定する
- 構造化ログを保ち(クライアント、エンドポイント、ステータスコード、レイテンシ、ペイロードサイズ)
- エンドポイントごとに主要指標を追跡する:エラー率、p95レイテンシ、スループット
スケーリングも異なります。ゲートウェイは共有のボトルネックになり得るので、スパイクやホットエンドポイントをさばけるようにしなければなりません。BFFはクライアントごとにスケールできるため、業務時間にWebトラフィックが跳ねてもモバイルが安定する、といった調整がしやすくなります。
インシデントでは障害の“移動先”がパターンによって変わります。ゲートウェイでは広範囲の5xxや認証失敗が出やすく、BFFではあるクライアント機能だけに影響が限定されることが多いです。ランブックはまずどこを見ればよいかを明確にしておき、フォールバックをシンプルに(タイムアウトよりも減らしたレスポンスを返すなど)しておいてください。
どう選ぶか:シンプルな意思決定プロセス
APIゲートウェイとBFFの選択は理論よりも日常のクライアントニーズに基づくべきです。
実用的な意思決定フロー
-
サーバーではなくクライアントから始める。サポートしているすべてのクライアント(Webアプリ、iOS、Android、パートナーAPI、内部管理)を書き出し、各主要画面が何を必要とするかをリストアップします。例えば同じ「顧客詳細」ビューがクライアントごとに異なるフィールドや呼び出しパターンを必要とするなら、クライアント固有の整形が強いシグナルです。
-
現状をマッピングする。現在のエンドポイントを取り、共通のもの(注文、支払い、ユーザーなどのコアドメイン操作)とプレゼンテーション寄りのもの(ダッシュボードのサマリ、ホーム画面結合ペイロード)をマークします。共通の部分はコアバックエンドに、プレゼンテーション寄りの部分はBFFの方が合うことが多いです。
-
どこに整形やルールを置くか決める。主にルーティング、認証、レート制限、キャッシュ、安全な公開/内部分離が必要ならゲートウェイが自然な場所です。本当に複数サービスの合成(6回の呼び出しを1つにするなど)が必要なら、そのロジックはテスト可能で読みやすいBFFコードに置きます。
-
実行可能なバージョニングと廃止ルールを決める。例えば「破壊的変更は新バージョン必須、廃止は90日保持」などです。ゲートウェイだけだと公開面をバージョン化して翻訳する形になるかもしれません。BFFならコアAPIは安定させ、クライアントごとのBFFエンドポイントだけをバージョン化できます。
-
ロールアウト計画と計測。変更前にベースライン指標(p95、画面あたりの呼び出し数、ペイロードサイズ、エラー率)を取ります。まず少数にロールアウトして比較し、問題がなければ拡大します。
単純な例:モバイルアプリが月次でリリースするのに対しWebポータルは日次でデプロイする場合、小さなモバイルBFFを用意するとモバイルを頻繁なバックエンド変更から守り、Webは速く動かし続けられます。
例:リリース速度が異なるWebポータルとモバイルアプリ
ある会社に、顧客ポータルのWebとフィールド作業用のモバイルアプリがあるとします。両方とも顧客、ジョブ、請求書、メッセージといった同じコアデータを必要とします。ポータルは週単位で変更され、モバイルはアプリストア審査や弱い通信環境への対応が必要で更新が遅いです。
問題はすぐに顕在化します。モバイルユーザーはコンパクトなレスポンス、少ない呼び出し、オフライン対応フロー(例:今日のジョブを一度ダウンロードして後で同期)を求めます。Webは常時オンラインで更新もしやすいため、より多くの呼び出しやリッチな画面で問題ありません。
選択肢A:安定したサービスの前にAPIゲートウェイ
ゲートウェイ優先の選択ではバックエンドサービスを大きく変えずに済みます。ゲートウェイが認証、ルーティング、ヘッダの調整、レート制限、簡単なフィールドマッピングなどを担当します。
バージョニングはサービスAPIレベルに置くことが多く、管理する要素が少ない利点があります。ただし、モバイル固有の変更をするときに広いバージョン(例:/v2)を導入せざるを得ないことがあり得ます。
エンドポイントの公開範囲は、ゲートウェイを唯一の公開口にすることで明確になりますが、ゲートウェイが到達できる範囲と公開するものを厳格に管理する必要があります。
選択肢B:モバイルに特化したBFF
モバイルBFFを置くと、モバイルアプリはモバイル画面や同期フロー向けに設計されたエンドポイントと話します。BFFはジョブ詳細、顧客、最新メッセージを集約し、フィールドを絞ってアプリの必要に合ったペイロードを返します。
変わる点:
- バージョニングはクライアントごとにしやすく、モバイルBFFをバージョン固定してWebは速く進めることができる
- モバイルのパフォーマンスが改善することが多い:往復が減り、レスポンスが小さくなる
- 公開と内部の分離が明確になる:BFFは公開されますが内部サービスは公開されない
よくあるミスと陥りやすい罠
APIゲートウェイ対BFFの議論で最大の罠は、ゲートウェイをミニバックエンドにしてしまうことです。ゲートウェイはルーティング、認証、レート制限、単純なリクエスト整形に優れていますが、業務ルールを詰め込むとテストやデバッグが困難になり、設定変更で壊れやすくなります。
BFFは逆の失敗をすることがあります:チームが画面単位や機能単位でBFFを作りすぎて保守が破綻するケースです。BFFは通常クライアント種別(Web、iOS、Android)や明確なプロダクト領域に対応させ、すべてのUIビューごとに作らない方が良いです。さもないと同じルールが十箇所で複製され、バージョニングが常時の仕事になります。
バージョニングのミスは極端から来ます。最初からすべてをバージョン化するとAPIを早々に凍結して、古い変種をずっと残すことになります。逆にまったくバージョンを導入しないと、意図せず破壊的な変更を出してしまいます。実務的には:小さな追加はバージョンせず、削除や意味の変化があるときにバージョンするのが良いルールです。
公開と内部の分離はチームが最も痛い目を見る箇所です。内部サービスをインターネットに直接さらす(たとえ一時的でも)と、内部の変更がアウトテージやセキュリティ事故に直結します。境界を明確に保ち、公開できるのはゲートウェイかBFFだけにしてください。
パフォーマンス問題は自己招集されることが多い:過大なペイロード、過度に多い往復、レイテンシの予算がない設計。例えばモバイルが注文ステータスと合計だけ必要なのに、フルの注文オブジェクト(各行アイテムや監査フィールドまで)を渡すと、セルラーでは毎回遅くなります。
注意すべきサイン:
- ゲートウェイ設定に「返金可否」や「VIPルール」など業務概念が含まれている
- BFFがサポートするクライアントより速いペースで増殖している
- APIバージョニング戦略を一文で説明できない
- 内部サービスのエンドポイントが公開インターネットから到達可能
- 「将来使うかも」でレスポンスがどんどん肥大化していく
クイックチェックリストと次のステップ
APIゲートウェイ対BFFの判断に迷ったら、実際に先に壊れるもの:リリース、ペイロード、セキュリティ境界に注目してください。
クイックチェックリスト
以下がいくつか「いいえ」なら、現在の構成はクライアントが増えると問題になります:
- あるバックエンドサービスを変更してもすべてのクライアントに同週更新を強いられずに済むか?
- 公開エンドポイント(インターネットに安全に晒せる)と内部エンドポイント(信頼できるシステムのみ)が明確に分かれているか?
- Webとモバイルは必要なものだけを受け取っているか(キッチンシンクで巨大なレスポンスを返していないか)?
- 変更を段階的にロールアウトして、エラーやレイテンシ、異常なトラフィックを早期に検知できるか?
- 各エンドポイントの契約を誰が所有し、破壊的変更を誰が承認するのか分かっているか?
次のステップ
回答をもとに計画を立ててください。目標は完璧なアーキテクチャではなく、出荷時の驚きを減らすことです。
API契約を平易な言葉で書き(入力、出力、エラーコード、変更可能な範囲)、所有モデルを決めます:誰がクライアントニーズ(Web/モバイル)を所有し、誰がコアドメインサービスを所有するか。バージョニングをどこに置くか(クライアントごとか中央か)を決め、従うべき廃止ルールを定めます。
大きなリファクタ前に基本的な監視を追加してください:リクエスト率、p95レイテンシ、エラー率、ペイロードサイズ上位のエンドポイント。リスクが高いクライアントフローをまずプロトタイプしてください。
もし AppMaster (appmaster.io) を使っているなら、実用的なアプローチはコアのビジネスロジックとデータモデルを生成されたバックエンドに置き、クライアントが本当に別のペイロード整形やリリース分離を必要とするときだけ薄いゲートウェイかBFF層を追加することです。
チェックリストに答えにくさを感じるなら、それは公開と内部の境界を厳しくしてエンドポイントを整理するサインです。大規模な変更を加える前に契約を単純化してください。
よくある質問
公開のエントリポイントが一つで、認証チェック、レート制限、ルーティングなどの共有コントロールが主な要件であれば、まずはAPIゲートウェイから始めましょう。Webとモバイルが明確に異なるペイロードや呼び出し数、独立したリリースサイクルを必要とする場合は、BFFを追加すると良いです。
ゲートウェイはエッジでの横断的関心事やトラフィック制御向けに最適化し、ルーティング、認証強制、基本的なリクエスト/レスポンス処理に集中させます。BFFはクライアント向けの合成(複数サービス呼び出しの結合や不要フィールドの削除)を行います。ただし、BFFもコアのビジネスルールの置き場にしてはいけません。
ゲートウェイはひとつのバージョン化された“玄関口”を提供するので説明は簡単ですが、古いバージョンを長くサポートしがちです。BFFはクライアントごとにバージョン管理できるため、モバイルは安定させつつWebを速く動かせますが、管理するサービスや契約が増えます。
原則として非互換な変更を避け、オプションのフィールド追加や新しいエンドポイント追加のような非破壊的な変更を優先してください。フィールド名変更、型変更、エンドポイント削除などのときは新しいバージョンを作るべきです。モバイルは更新が遅れることを前提にしてください。
内部サービスは非公開にし、公開可能なのはゲートウェイかBFFだけにします。レスポンスをフィルタしてクライアントに必要なものだけ返し、各ルートごとの認可を厳格に設定して、管理用アクションが単にログインしているだけで到達できないようにしてください。
クライアントが多数の連続した呼び出しを行うような場合はBFFを使うと速くなることが多いです。BFFでサーバー側集約を行えば、モバイルのセルラーネットワークでの往復遅延を減らせます。ゲートウェイも追加のホップになりますが、軽量に保ち、レイテンシとペイロードサイズを測定しましょう。
ゲートウェイは共有の絞り込み点になり得るので設定ミスや障害が全クライアントに影響します。BFFは変更の爆発範囲を小さくできますが、デプロイや監視、オンコールの対象が増えます。運用面ではどちらにも一長一短があります。
リクエスト全体を追跡できる相関IDを使い、ゲートウェイ/BFFと全下流サービスで渡してください。エンドポイントごとにエラー率、p95レイテンシ、スループット、ペイロードサイズなどの指標を少数追跡しておくと、性能劣化が早く見つかります。
よくある失敗は、ゲートウェイに業務ルールを詰め込みすぎることと、スクリーンごとにBFFを作りすぎることです。前者はテストやデバッグが難しくなり、後者はルールの重複とバージョン管理作業の爆発を招きます。
コアのデータモデルとビジネスプロセスを生成されたバックエンドに置き、クライアントごとの本当に必要な場合にのみ薄いゲートウェイやBFFレイヤーを追加するのが実用的です。AppMaster (appmaster.io) を使う場合は、生成されるGoバックエンドにドメインの安定したエンドポイントを残し、モバイル向けの集約やペイロード削減だけを小さなレイヤーで実装すると良いでしょう。


