レートリミティング

英語名 Rate Limiting
読み方 レート リミティング
難易度
所要時間 実装に1〜3日
提唱者 ネットワーク工学・通信制御の分野
目次

ひとことで言うと
#

一定時間内に受け付けるリクエスト数に上限を設け、超過分を拒否または遅延させることで、サービスを過負荷や悪用から守る仕組み。

押さえておきたい用語
#

押さえておきたい用語
トークンバケット
一定速度でトークンが補充され、リクエスト時にトークンを消費するアルゴリズム。バースト許容と安定制限のバランスが良い。
スライディングウィンドウ
直近N秒間のリクエスト数で制限する方式。固定ウィンドウより滑らかな制御が可能。
HTTP 429
Too Many Requestsを示すHTTPステータスコード。制限超過時に返却する標準レスポンス。
Retry-After
制限超過時にクライアントに再試行可能なタイミングを伝えるHTTPレスポンスヘッダー。
バースト
短時間に集中して送信されるリクエストの急増。正当な利用でもバーストは発生する。

レートリミティングの全体像
#

アルゴリズム選択と多層防御の構造
アルゴリズム選択固定ウィンドウ: 時間枠でリセットスライディング: 直近N秒で計算トークンバケット: バースト対応可リーキーバケット: 安定流量制限ルール設計制限単位: IP / APIキー / ユーザープラン別: Free 60/分, Pro 600/分429 + Retry-After で応答X-RateLimit-* ヘッダー付与分散環境での一貫性Redis等でカウンターを一元管理アトミック操作でレースコンディション防止
レートリミティング導入フロー
1
アルゴリズム選択
用途に合った方式を選ぶ
2
ルール定義
粒度と制限値を決める
3
レスポンス設計
429+ヘッダーで透明に通知
4
分散対応
Redisで一貫性を確保

こんな悩みに効く
#

  • 特定のユーザーやクライアントが大量リクエストを送り、他のユーザーに影響が出ている
  • APIが想定以上のトラフィックで応答不能になる
  • ボットやスクレイパーにリソースを食い潰される

基本の使い方
#

ステップ1: レートリミットのアルゴリズムを選択する

用途に合ったレート制限アルゴリズムを選ぶ。

  • 固定ウィンドウ: 時間枠ごとにカウントをリセット(例: 1分間に100回まで)
  • スライディングウィンドウ: 直近N秒間のリクエスト数で制限(より滑らかな制御)
  • トークンバケット: 一定速度でトークンが補充され、リクエスト時にトークンを消費。バースト対応可能
  • リーキーバケット: リクエストをキューに入れ、一定速度で処理。安定した流量を実現

ポイント: トークンバケットが最も汎用的。バースト許容と安定制限のバランスが良い。

ステップ2: 制限の粒度とルールを定義する

何を基準に、どの程度制限するかを決める。

  • 制限の単位: IPアドレス、APIキー、ユーザーID、エンドポイントなど
  • 制限値: 「1分間に60リクエスト」「1日10,000リクエスト」など
  • 階層的ルール: プランごとに異なる制限値(Free: 100/分、Pro: 1000/分)

ポイント: 制限の粒度が粗すぎると正当なユーザーを巻き込み、細かすぎると管理が煩雑になる。

ステップ3: レスポンスヘッダーとエラー応答を設計する

クライアントが制限状況を把握できる情報を返す。

  • X-RateLimit-Limit: 制限値
  • X-RateLimit-Remaining: 残りリクエスト数
  • X-RateLimit-Reset: 制限リセットまでの時間
  • 制限超過時はHTTP 429 Too Many Requestsを返し、Retry-Afterヘッダーを付与する

ポイント: クライアントに制限状況を透明に伝えることで、適切なリトライ実装を促す。

ステップ4: 分散環境での一貫性を確保する

複数サーバーでレートリミットの状態を共有する。

  • Redisなどのインメモリストアでカウンターを一元管理する
  • APIゲートウェイ層で統一的に制限を適用する
  • レースコンディションを防ぐためにアトミック操作を使用する

ポイント: ローカルカウンターだけでは、ロードバランサー配下で制限が緩くなる。

具体例
#

例1:公開APIにレートリミティングを導入する

状況: SaaSプロダクトの公開API。特定のクライアントが1秒間に数百リクエストを送り、他のユーザーのP95レスポンスタイムが200ms→800msに悪化。

設計: トークンバケットアルゴリズム。Redisでカウンター管理。

  • Freeプラン: 60リクエスト/分(バースト許容: 10/秒)
  • Proプラン: 600リクエスト/分(バースト許容: 30/秒)
  • 制限超過時: HTTP 429 + Retry-After: 5 を返却

結果: 過剰リクエストが制限され、全ユーザーのP95レスポンスタイムが200ms→80msに改善。APIキーごとの使用状況が可視化され、プランアップグレードの営業機会も創出。

例2:ログインAPIへのブルートフォース攻撃を防御する

状況: ログインAPIに対して1つのIPアドレスから1秒間に50回のリクエスト。パスワードのブルートフォース攻撃の疑い。

対策: IPアドレス単位 + アカウント単位の二重レートリミット。

  • IPアドレス: 10リクエスト/分(ログインAPIのみ)
  • アカウント: 5回失敗で15分ロック
  • 制限超過時: 通常の429ではなく意図的に遅延レスポンス(タールピット)を返す

結果: ブルートフォース攻撃の成功率がゼロに。正当なユーザーへの影響なし(通常のログインは1分に10回も試行しない)。

例3:内部マイクロサービス間のカスケード障害を防止する

状況: 注文サービスが在庫サービスを呼び出し。在庫サービスの障害時に、注文サービスがリトライを繰り返し、在庫サービスに毎秒5,000リクエストが殺到。復旧が遅延する悪循環。

対策: サービス間通信にもレートリミットを適用。

  • 注文→在庫: 最大1,000 RPS(通常ピークの2倍)
  • 超過時はサーキットブレーカーと連携して即座にフォールバック
  • 在庫確認は「在庫あり」をキャッシュから返し、後で整合性を確認

結果: 在庫サービスの障害時、注文サービスの応答時間は50ms以内を維持(キャッシュフォールバック)。在庫サービスの復旧時間が10分から3分に短縮。

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

  1. 制限超過時に情報を返さない — 429だけ返してRetry-Afterやリセット時刻を伝えないと、クライアントが即座にリトライして更に負荷をかける。レスポンスヘッダーで制限情報を透明に伝える
  2. 全エンドポイントに同じ制限をかける — 軽量なGETと重いPOSTに同じ制限は不適切。エンドポイントの負荷特性に応じて制限値を分ける
  3. 内部サービス間通信にもそのまま適用する — 内部通信に外部向けのレートリミットをかけると、正常なバッチ処理が止まる。内部通信は別ルールを設定する
  4. 制限値を本番データなしで決める — 勘で制限値を設定すると正当なユーザーを制限してしまう。本番のアクセスパターンを分析してから制限値を決める

まとめ
#

レートリミティングはAPIを守る基本的な防御機構。適切なアルゴリズム選択、クライアントへの透明な情報提供、分散環境での一貫性確保が成功のポイント。導入することでサービスの安定性を確保しつつ、利用状況の可視化という副次的なメリットも得られる。