レート制限・フェイルオーバー・冗長化

AI Navigate Original / 2026/5/16

共有:

要点

  • LLM は外部依存・従量・たまに落ちる前提で守りを設計する
  • プロバイダ上限前に自前制御し、ユーザー単位クォータを置く
  • 障害時は代替モデルへ切替、バックオフ再試行、劣化時フォールバック
  • 上限とキャッシュでコストを守り、影響大の変更は段階展開

LLM を使ったアプリは、外部のAPIに依存し、使った分だけ課金され、ときどき混雑や障害で応答が返らない——この3つを前提に作る必要があります。デモは動いても、本番で同時アクセスが増えたり提供元が一時的に落ちたりすると簡単に崩れます。この章では「上限に当たる前に自分で制御する(レート制限)」「落ちても切り替えて止めない(フェイルオーバー)」「無駄な課金を防ぐ(コストの守り)」という、守りの設計を具体的に整理します。

Why It Breaks

そもそも、なぜ守りが要るのか。LLM の API には提供元が決めた上限があり、これを超えると 429 Too Many Requests というエラーが返ってきます。上限は主に2つの指標で測られます——RPM(1分あたりのリクエスト数)とTPM(1分あたりのトークン数=入力+出力の合計)。多くのプロバイダはこの上限を「累計支払額に応じたティア(段階)」で引き上げる方式を採っており、たとえば2026年時点で OpenAI は最上位ティアで非常に大きな上限を出す一方、登録直後の低いティアでは桁違いに小さい上限から始まります。Anthropic も RPM・入力TPM・出力TPM を別々に制限しており、生成量が多い用途では「出力トークン/分」が先に効いてくる、といった具合です。

大量アクセス あなたの アプリ 上限 (RPM / TPM) LLM API 提供元 429 Too Many Requests

FIG.1 上限を超えたリクエストは弾かれて 429 で返る——だから「当たる前に」自分で制御する

01レート制限:上限に当たる前に自分で制御する

守りの第一歩は、提供元の上限に当たる前に、自分のアプリ側で流量をコントロールすることです。上限に当たってから慌てるのではなく、当たらないように整える発想です。実務でよく使う手は次の通りです。

  • キューイング:リクエストを一度待ち行列に入れ、1分あたりの送信数を上限内に収まるよう間引いて送る。突発的なアクセス集中(スパイク)を平準化できます。
  • バックオフ(指数的後退):429 が返ったら即リトライせず、待ち時間を 1秒 → 2秒 → 4秒…と倍々に伸ばして再送する。全クライアントが同時に再送して再び詰まるのを避けるため、待ち時間に少しランダムなブレ(ジッター)を足すのが定石です。
  • ユーザー単位のクォータ:1人(または1組織)あたりの利用量に上限を設ける。これは「濫用・暴走を防ぐ」ためで、後述のコスト暴走対策にも直結します。
経過時間 429 +1s 429 +2s 429 +4s(+ジッター) 成功 待ち時間を倍々に伸ばし、混雑が解けたら通す

FIG.2 指数バックオフ+ジッター——即リトライの「再殺到」を避けながら回復を待つ

上限は「提供元が守るもの」ではなく、自分が当たらないように設計するもの

02フェイルオーバー・冗長化:落ちても止めない

どれだけ丁寧に流量を整えても、提供元そのものの障害(一時的な停止、特定モデルの不調、長いタイムアウト)は起こり得ます。ここで効くのが「切り替えて止めない」設計、すなわちフェイルオーバーと冗長化です。考え方はシンプルで、応答が得られなかったら、別の手段に順番に切り替えること。

01

代替モデルへの切替(フォールバック連鎖)

主モデルが 429・タイムアウト・エラーを返したら、あらかじめ決めた優先順位で次の候補へ自動的に切り替えます。実務では「①主モデル → ②同じ提供元の別モデル → ③別提供元のモデル」と、最低でも複数段の連鎖を組むのが定石です。LiteLLM・OpenRouter・各種 LLM ゲートウェイは、この優先順リストによる自動フォールバックを標準機能として持っています。

02

タイムアウト+リトライ(冪等性に注意)

応答が一定時間内に返らなければ打ち切り、安全に再試行します。ただし「課金や副作用のある処理」を素朴に再送すると二重実行になりかねません。同じリクエストを2回送っても結果が1回分になるよう、リクエストに一意のキー(idempotency key)を付けて重複を弾く=冪等に作るのが鉄則です。

03

サーキットブレーカー(連鎖故障の遮断)

ある提供元が立て続けに失敗しているのに毎回そこへ投げ続けると、待ち時間と失敗が積み重なって全体が遅くなります。一定回数(実運用では概ね5回前後が目安)連続で失敗したら、その提供元を一時的に切り離し、数十秒の冷却後に少しだけ試して回復を確認する。これがサーキットブレーカーです。

04

劣化時のフォールバック(壊れるより、控えめに動く)

全ての候補がダメなときでも、画面を真っ白にしない。キャッシュ済みの回答を返す/簡易な定型応答に切り替える/「いまAIが混み合っています。担当者にお繋ぎします」と人手へ誘導する——機能を全部止めるのではなく、品質を一段下げてでも止めないのが優雅な劣化(graceful degradation)です。

① 主モデル 提供元A 失敗 ② 別モデル 提供元A 失敗 ③ 別提供元 提供元B 応答 優先順位の上から順に試し、成功した時点で返す(最低3段が目安)

FIG.3 フォールバック連鎖:同提供元の別モデル → 別提供元、と段階的に逃がす

03コストの守り:暴走させない・払いすぎない

従量課金は「使った分だけ」が魅力であると同時に、設計を誤ると請求が青天井になる危険でもあります。バグでループした、悪意ある利用で大量呼び出しされた、想定の10倍のアクセスが来た——こうした事故から守る仕組みを最初から入れておきます。

暴走を止める仕掛け払いすぎを減らす仕掛け
支出のソフト/ハード上限とアラート(OpenAI などはプロジェクト単位の予算上限・しきい値通知を提供)キャッシュで同一・類似リクエストの再課金を回避
想定外スパイクの遮断(前述のクォータ・サーキットブレーカー)用途に応じた安いモデルへの振り分け(簡単な処理に高級モデルを使わない)
異常検知(短時間に呼び出し急増→自動で絞る/止める)長い文脈・無駄な出力を削るプロンプト最適化

とくに効果が大きいのがキャッシュです。同じ・あるいは意味的に近い質問が繰り返される用途では、毎回モデルに投げ直さず保存済みの回答を返すだけで課金が消えます。やり方は2系統あります。

プロンプトキャッシュ

長い共通の前置き(システムプロンプト・ナレッジ)を提供元側でキャッシュし、再利用時の入力課金を大幅に下げる。読み出しは標準入力の約1/10の単価になる提供元もあり、繰り返しの多い用途で効きます。

セマンティックキャッシュ

「文字列が完全一致」ではなく意味が近い質問を拾って既存回答を返す。実運用での命中率は2〜4割程度が現実的(ベンダー宣伝の高数値を鵜呑みにしない)。

結果キャッシュ

同一入力に対する完成済みの回答そのものを保存。FAQ など定型質問が多いほど威力を発揮します。

Observability First

守りの設計は「観測」とセットで初めて機能する

レート制限もフェイルオーバーもコスト上限も、いま何が起きているかが見えなければ調整できません。リクエスト数・トークン数・遅延・エラー率(429 や 5xx)・フォールバック発生回数・キャッシュ命中率・1リクエストあたりコスト——これらを継続的にログに残し、しきい値を超えたらアラートを出す。前章の「観測」が土台にあって初めて、本章の守りが動き出します。

観測 指標・ログ・アラート 守りの調整 上限・切替・キャッシュ 安定した本番 落ちない・払いすぎない 見える → 直せる → 安定する のループ

FIG.4 観測なしの守りは「勘で調整」になる——計測してから整える

04変更そのものを安全に:段階展開とロールバック

守りの設計を入れる・変える作業自体も、本番に影響します。モデルの切替、上限値の変更、フォールバック連鎖の組み替えは、いずれも「やってみたら全ユーザーに即影響」が起こり得る変更です。だからこそ次を前提にします。

  • 段階展開:いきなり全員に出さず、一部トラフィックだけに適用して様子を見る(カナリア)。
  • 機能フラグ:問題があればコードを戻さずスイッチひとつで即オフにできるようにしておく。
  • ロールバック前提:「失敗したらこの1手順で元に戻る」を変更前に用意しておく。

料金・上限・モデルの仕様は頻繁に変わります。本章で挙げた具体的な数値や単価も時点の目安にすぎないので、実装前に必ず各提供元の公式ドキュメントで最新を確認してください。

05本章のまとめ

本番化の核心は観測+守りの設計です。「動いた」と「動き続ける・落ちても壊れない・払いすぎない」はまったくの別物。レート制限で当たる前に整え、フェイルオーバーで落ちても止めず、コストの守りで暴走を防ぐ——そしてその全部を、観測で見える状態にして段階的に調整していく。この3点セットがそろって初めて、LLM アプリは本番で信頼して使えるものになります。