2025年10月12日·1分で読めます

パブリックAPIのレート制限:実用的なクオータとロックアウト

実ユーザーをブロックせずに不正利用を防ぐパブリックAPI向けレート制限:実用的な上限、キー単位クオータ、ロックアウト、導入のコツ。

パブリックAPIのレート制限:実用的なクオータとロックアウト

レート制限が実際に解決している問題\n\nパブリックAPIのレート制限はユーザーを罰するためのものではありません。トラフィックがおかしくなったときにサービスを利用可能に保つための安全弁です。その「おかしさ」は悪意あるものかクライアントのバグかもしれません。\n\n「不正利用」は最初は普通に見えることが多いです:データを取りに全エンドポイントを巡回するスクレイパー、総当たりのログイン試行、認証ルートに対するトークン詰め、タイムアウト後に同じリクエストを短時間で何度も再試行するクライアントなど。時には誰も攻撃していないこともあります。モバイルアプリのアップデートでキャッシュルールが間違っていて、突然すべての端末が毎秒APIをポーリングし始めることもあります。\n\nやるべきことは明確です:実際のユーザーの通常の利用を妨げずに稼働率を守り、コストを管理すること。バックエンドがメーター課金(計算、データベース、メール/SMS、AI呼び出し)なら、騒がしいアクター一人で急に請求が膨らむ可能性があります。\n\nただし、レート制限だけでは不十分です。監視と明確なエラーレスポンスがなければ、サイレントな失敗、混乱した顧客、そして「APIが落ちている」といったサポートチケットが発生します。\n\n完全なガードレールは通常いくつかの要素で構成されます:\n\n- レートリミット:短いウィンドウ(秒/分)での上限、瞬発的なスパイクを止める。\n- クオータ:長いウィンドウ(1日/月)での予算管理、利用を予測可能にする。\n- ロックアウト:明らかに悪質なパターンに対する一時的なブロック。\n- 例外:信頼できる統合、内部ツール、VIP顧客のための許可リスト。\n\nAppMaster のようなプラットフォームでAPIバックエンドを構築している場合でも、これらのルールは重要です。コードがきれいに生成されても、1つの悪いクライアントでサービス全体が影響を受けないようにデフォルトの保護を用意しておきましょう。\n\n## 重要用語:レートリミット、クオータ、スロットリング、ロックアウト\n\n用語は混ざりがちですが、それぞれ異なる問題を解決し、ユーザーにとっての感触も異なります。\n\n### レートリミット、クオータ、同時接続制限:各用語の意味\n\nレートリミットは速度制限です:クライアントが短いウィンドウ内に行えるリクエスト数(秒ごと、分ごと)。クオータは予算です:より長い期間(1日、1か月)での総利用量。同時接続制限は同時に進行できるリクエスト数の上限で、リクエスト率が平常でも高コストなエンドポイントには有用です。\n\nどこに制限を付けるかも重要です:\n\n- IPごと:簡単だが共有ネットワーク(オフィス、学校、モバイルキャリア)には厳しい。\n- ユーザーごと:ログインアプリに適しているが、信頼できる識別が前提。\n- APIキーごと:パブリックAPIで一般的、所有者が明確でメッセージしやすい。\n- エンドポイントごと:あるルートが他より重い場合に有効。\n\n### スロットリングとブロッキング、ロックアウトの位置づけ\n\nソフトスロットリングはクライアントを遅らせます(遅延やバースト容量の制限)ので、ワークフローを壊さずに回復できます。ハードブロックは即時にリクエストを拒否し、通常は HTTP 429 を返します。\n\nロックアウトは通常の 429 より強いものです。429 は「すぐに再試行して」と伝えますが、ロックアウトは「ある条件が満たされるまで停止して」と伝えます(クールダウン期間、手動レビュー、キーのリセットなど)。ロックアウトは認証情報の総当たり、積極的なスクレイピング、繰り返される無効な認証など、明らかな悪用シグナルに対して使うべきです。\n\nAppMaster のようなツールでAPIを作るときは、短いウィンドウの制限でバーストを抑え、長いクオータでコストを管理し、ロックアウトは繰り返す悪質な振る舞いにのみ使う、といった分離を心がけてください。\n\n## 過度に推測せず実用的な制限を選ぶ\n\n良い制限は一つの目標から始まります:通常のユーザーが作業を終えられるようにしつつ、バックエンドを守ること。初日から完璧な数字は必要ありません。安全なベースラインと、調整する仕組みがあれば十分です。\n\nシンプルな出発点は、あなたのAPIの種類に合わせたキー単位の制限です:\n\n- 低トラフィック:キーあたり 1 分間に 60〜300 リクエスト\n- 中トラフィック:キーあたり 1 分間に 600〜1,500 リクエスト\n- 高トラフィック:キーあたり 1 分間に 3,000〜10,000 リクエスト\n\n次にエンドポイントごとに分けます。読み取りは通常安く、より高い制限を与えられます。書き込みはデータ変更や追加ロジックを伴うため、より厳しい上限にするべきです。一般的なパターンは GET ルートで 1,000/分、POST/PUT/DELETE で 100〜300/分のようなものです。\n\n検索、レポート生成、エクスポート、ファイルアップロード、複数テーブルにアクセスするものや重いビジネスロジックを走らせるものは別枠で扱いましょう。もしバックエンドがビジュアルワークフロー(例えば Business Process フロー)を使っているなら、ステップが増えるごとに負荷は増えます。\n\nバーストに備えて短いウィンドウと長いウィンドウの組み合わせを用意します。一般的には 10 秒と 10 分の組み合わせがよく使われます。これにより素早いクリックには耐えつつ、スクレイパーに無制限の速度を与えません。\n\nまた、クライアントが制限を超えたときに何が起きるかを決めてください。多くのパブリックAPIは HTTP 429 を返し、明確な再試行時間を示します。エクスポートのように遅延しても安全な仕事なら、ハードブロックの代わりにキューイングして実際のユーザーに結果を返すことを検討してください。\n\n## 公平に感じられるキー単位クオータの設計\n\nキー単位のクオータは、通常顧客の使い方に一致するため最も公平です:1 アカウントに1キー、責任が明確です。IP ベースの制限は有用ですが、無実のユーザーを罰することが多いです。\n\n共有IPが問題になるのは明白です。オフィス全体が1つのパブリックIPを使っていたり、モバイルキャリアが多数のデバイスを少数のIPプールに入れることがあります。IP単位の上限に頼ると一人の騒がしい利用者が皆を遅くすることがあります。キー単位のクオータはそれを避けられます。軽い IP 上限は明らかな洪水のバックストップとして残しておきましょう。\n\nクオータを公平に感じさせるために、顧客プランに結びつけつつ新規ユーザーを締め付けないようにします。フリーやトライアルキーは実際のテストに使えるが、あなたに損害を与えるスケールではないようにするのが良いパターンです。一般的にはバーストには寛容、持続率は控えめ、日次クオータはプランに合わせます。\n\n予測可能なキー単位ポリシーの例:\n\n- 短いバーストを許容し(ページ読み込みやバッチインポート)、その後は一定のレートを守らせる。\n- スクレイピングやループを防ぐためにキーごとの日次上限を設ける。\n- プランごとに上限を上げるが、構造は同じにして挙動を一貫させる。\n- 新しく作成されたキーには低めの上限を適用し、良好な履歴ができたら緩和する。\n- 明らかな洪水を検出するために小さな IP ごとの上限を残しておく。\n\nキー共有や自動登録を抑止するために高度な監視は不要です。まずは挙動の異常(突然のジオロケーション変化、短時間に多数の異なるIPからのアクセス、同一ソースからの大量の新規キー作成)といった単純なチェックを入れ、まずはフラグを立てて遅延させ、繰り返しがあればロックアウトする、という流れで十分です。\n\n匿名トラフィックにはより厳しい上限が妥当です。トライアルキーを提供するなら厳しくレート制限し、限度を上げる前に基本的な検証ステップを要求してください。公開フォームを提供している場合は匿名用の別エンドポイントを設けて残りのバックエンドを保護する方法もあります。\n\nAppMaster でAPIを構築すると、認証、ビジネスルール、レスポンス処理が一箇所にまとまるのでキー単位のロジックを一貫して管理しやすくなります。\n\n## クライアントに優しいレスポンスとヘッダー(回復を助ける)\n\nレート制限が長期に機能するには、クライアントが何が起きたかを理解できることが必要です。ステータスコードやフィールドの意味をエンドポイント間で一貫させることを目指してください。\n\nクライアントが制限に達したときは HTTP 429(Too Many Requests)を返し、明確なメッセージと具体的な待ち時間を示しましょう。最も簡単に効果があるのは Retry-After ヘッダーを追加することです。簡単なクライアントでも正しく待てます。\n\n少数のヘッダーを用意しておくと、制限が自明になります。名前を一貫させ、成功レスポンス(クライアントが自分でペース配分できるように)と 429 レスポンスの両方に含めてください:\n\n- Retry-After: 再試行までの秒数\n- X-RateLimit-Limit: 現在のウィンドウで許可されるリクエスト数\n- X-RateLimit-Remaining: 現在のウィンドウで残っているリクエスト数\n- X-RateLimit-Reset: ウィンドウがリセットされる時刻(エポック秒またはISO時刻)\n- X-RateLimit-Policy: "60 requests per 60s" のような短い説明\n\nエラーボディは成功レスポンスと同じくらい構造化しておきます。一般的なパターンは、安定した code、人間向けの message、回復のヒントを含むエラーオブジェクトです。\n\njson\n{\n "error": {\n "code": "rate_limit_exceeded",\n "message": "Too many requests. Please retry after 12 seconds.",\n "retry_after_seconds": 12,\n "limit": 60,\n "remaining": 0,\n "reset_at": "2026-01-25T12:34:56Z"\n }\n}\n\n\nクライアントに 429 を見たらどうバックオフするかを伝えましょう。指数バックオフ(1s、2s、4s、上限は 30〜60 秒など)は良いデフォルトです。いつ再試行を止めるべきかも明示しておくと親切です。\n\nクオータに近づいているとき(例えば 80〜90%)は警告フィールドやヘッダーで事前に通知して、クライアントが失敗する前に速度を落とせるようにしてください。これは特に一つのスクリプトが複数ルートに短時間でアクセスして予想より早く予算を使い切る場合に重要です。\n\n## ステップバイステップ:制限とクオータの簡単な導入計画\n\n制限は一度きりのファイアウォール設定ではなく、プロダクトの挙動として扱うと導入がうまくいきます。目的は変わらず:バックエンドを守りながら通常の顧客を動かし続けること。\n\nまずはクイックインベントリから。すべてのエンドポイントを列挙し、コスト(CPU、DB、サードパーティ呼び出し)とリスク(ログイン、パスワードリセット、検索、ファイルアップロード)でマークします。これにより一律の制限を避けられます。\n\n導入順の例:\n\n- エンドポイントをコストとリスクでタグ付けし、厳格にすべきもの(ログイン、バルクエクスポート)を決める。\n- 識別キーの優先順位を決める:まず API キー、次にユーザーID、最後にIP をフォールバックとして。\n- 短いウィンドウの制限(10 秒単位や分単位)を追加してバーストとスクリプトを止める。\n- 長いウィンドウのクオータ(時間単位や日単位)を追加して持続的な利用を抑える。\n- 運用用のモニタや信頼できるシステムのために許可リストを用意し、業務に支障が出ないようにする。\n\n最初のリリースは保守的に始めましょう。後から緩和する方が、怒ったユーザーを解除するよりずっと簡単です。\n\n監視と調整を続け、ポリシーにバージョン管理を導入してください。どれだけのリクエストが制限に引っかかったか、どのエンドポイントがトリガーしたか、どのキーが影響を受けたかを追跡します。数値を変えるときは API 変更のように扱い、文書化し段階的に展開し、新旧ルールを分けてロールバックを容易にします。\n\nAppMaster でAPIを作るなら、エンドポイントとビジネスロジックに沿ってこれらのルールを設計することで、各ワークフローの実コストに合わせた制限ができます。\n\n## ドラマを起こさないロックアウトワークフロー\n\nロックアウトはシートベルトのような役割です。明らかな不正を素早く止めつつ、通常のユーザーには明確な復旧方法を残すべきです。\n\n落ち着いたアプローチは段階的なペナルティです。クライアントが悪意あるとは限らない(設定ミスかもしれない)と仮定し、同じパターンが繰り返されたときだけエスカレートします。\n\n### シンプルな進行階段\n\n実装と説明が簡単な少数ステップを使いましょう:\n\n- 警告:キーが上限に近づいていることとリセット時刻を通知。\n- 減速:そのキーに対して短い遅延や秒間上限の強化を適用。\n- 一時ロックアウト:数分単位のブロック(時間ではなく分)と正確な解除時刻を返す。\n- 長めのロックアウト:複数ウィンドウに渡る繰り返しがあった場合に適用。\n- 手動レビュー:意図的と思われるパターンや繰り返しの場合の最終手段。\n\n何をロックするかも重要です。API キーごとが通常は最も公平で、呼び出し元をターゲットにできます。アカウントごとはキーを回転した場合に有用です。匿名トラフィックには IP ごとを使うと誤検知が増えます。深刻な不正の場合は複合シグナル(キーをロックしつつその IP に対して追加のチェックを要求する)を使ってもよいですが、影響範囲は小さく保ちましょう。\n\nロックアウトは時間ベースにしてシンプルなルールにします:「14:05 UTC までブロック」「30 分の良好な挙動でリセット」など。自動化されたシステムに対して永続的な禁止は避けてください。バグのあるクライアントはループして短時間で上限を使い切ることがあるので、ペナルティは時間とともに減衰するように設計します。低レートの持続期間を置けばペナルティ段階を下げる、という具合です。\n\nAppMaster でAPIを構築しているなら、この階段はストアドカウンタと Business Process による判定(allow, slow, block)とキーの解除時刻の書き込みで簡単に実装できます。\n\n繰り返しの違反者には手動レビューの流れを用意してください。ユーザーと争わないこと。リクエストID、タイムスタンプ、APIキー名を求めて証拠に基づいて判断します。\n\n## 誤検知を招く一般的なミス\n\n誤検知は防御が通常のユーザーをブロックしてしまう状況です。ルールが実際の利用に対して単純すぎると起こります。\n\n典型的なミスはすべてに同じグローバル制限を適用することです。安価な読み取りと高コストなエクスポートを同じ扱いにすると、安価な方を過剰に守るか、高コストの方を守れないかの二択になります。エンドポイントのコストで分け、重い経路には厳しい制限を設けましょう。\n\nIP のみの制限も落とし穴です。多くの実ユーザーが1つのパブリックIPを共有している(オフィス、学校、モバイルキャリア)ため、一人の重い利用者が皆をブロックすることになります。まずは API キーごとの制限を優先し、IP は明らかな悪用の二次信号としてください。\n\nリミッタの障害も誤検知を生みます。リミッタストアが落ちたときに「閉じる(fail closed)」にすると API 全体が落ちます。「開く(fail open)」にするとスパイクを招く可能性があります。明確なフォールバックを選び、エッジで小さな緊急キャップを維持し、非クリティカルなエンドポイントはグレースフルに劣化させましょう。\n\nクライアント側の扱いも大切です。汎用的な 429 を返すとユーザーはさらにリトライして状況を悪化させます。必ず Retry-After を返し、エラーテキストは具体的に("このキーのリクエストが多すぎます。30 秒後に再試行してください。")してください。\n\n最も避けやすい問題は秘密主義です。制限が非公開だと、顧客が本番負荷で初めて当たったときにそれをバグだと感じます。シンプルなポリシーを共有し、安定させておきましょう。\n\n誤検知を避けるための簡単チェックリスト:\n\n- 高コストと低コストのエンドポイントで制限を分離する\n- 優先的に API キーで制限し、IP のみにはしない\n- リミッタが利用不可の時の挙動を定義する\n- 明確な Retry-After を含む 429 レスポンス\n- 制限を文書化し、実施前に告知する\n\nAppMaster を使っている場合は、エンドポイントごとに別のキャップを設定し、一貫したエラーペイロードを返すことでクライアントが推測なしにバックオフできるようにしましょう。\n\n## 実用的な監視とアラート\n\nレート制限が機能するには、リアルタイムで何が起きているか見えることが前提です。目標はすべてのスパイクを捉えることではなく、障害や顧客の不満につながるパターンを早期に発見することです。\n\nボリュームと意図の両方を説明する小さな信号セットから始めましょう:\n\n- 分ごとのリクエスト数(全体とキーごと)\n- 429 発生率(スロットルされたリクエスト)と 5xx 発生率(バックエンドの痛み)\n- 401/403 の繰り返し(キー不正、認証情報の詰め、クライアント設定ミス)\n- ボリュームやコストで上位のエンドポイント(遅いクエリ、重いエクスポート)\n- 突然トップ10に現れた未知のエンドポイント\n\n「悪いトラフィック」と「新機能・リリースによる増加」を分けるために、ダッシュボードにデプロイ時間、フィーチャーフラグ、マーケティング送信のコンテキストを加えてください。リリース直後にトラフィックが跳ね上がり、429/5xx の比率が安定していれば成長の可能性が高いです。特定のキー、IPレンジ、重いエンドポイントに集中しているなら疑わしい行動として扱います。\n\nアラートは退屈で良いです。閾値とクールダウンを使って同じイベントで毎分ページが飛ばないようにします:\n\n- 429 発生率が X% を超え 10 分続く場合、1 時間に1回通知\n- 5xx が Y% を超え 5 分続く場合、即時ページング\n- 単一キーがクオータを Z% 超過して 15 分続く場合、調査を開始\n- 401/403 が分あたり N を超える場合、不正の可能性としてフラグ\n\nアラートが出たら短いインシデントノートを残してください:何が変わったか、観測したもの(上位キー/エンドポイント)、調整した内容(制限、キャッシュ、一時ブロック)。これらのノートが時間とともに実際のプレイブックになります。\n\n例:新しい検索エンドポイントをローンチしてトラフィックが倍増したとします。もし多くの呼び出しが多くのキーに分散しているなら、キーごとのクオータを少し上げてエンドポイントを最適化します。もし一つのキーがエクスポートを延々と叩いて遅延を引き起こしているなら、そのエンドポイントだけ別枠で上限を設け、所有者に連絡します。\n\n## ローンチ前後の簡単チェックリスト\n\nうまく動いているときは設定は退屈です。このチェックリストは誤検知や明白なギャップを検出します。\n\n### 新しいエンドポイントをリリースする前に\n\nステージングで、そしてリリース直後に以下を確認してください:\n\n- 識別:リミッタが正しいキーで動作しているか(まず API キー、その後ユーザーやIP)、キー回転時に古いペナルティが引き継がれないか。\n- 制限:デフォルトのキー単位クオータを設定し、エンドポイントのコストに応じて調整(安価な読み取り vs 高コストな書き込み)。\n- レスポンス:安定したステータスと回復情報(再試行時間、残り予算、安定したエラーコード)を返す。\n- ログ:誰が制限されたか(キー/ユーザー/IP)、どのルートで、どのルールが発火したか、サポート用のリクエストIDを記録する。\n- バイパス:モニタや信頼できる統合のための緊急許可リストを保持する。\n\nAppMaster 上で構築しているなら、新しい API エンドポイントごとにコスト層を決めるのが有効です:単純なルックアップは寛容に、重いビジネスロジックを呼ぶものは最初から厳しく。\n\n### インシデント発生時(不正または突然のトラフィック増)\n\nバックエンドを守りつつ実ユーザーが回復できるように:\n\n- リスクの低いルート(多くは読み取り)だけ一時的に上限を上げてエラー率を監視。\n- 調査中は既知の良い顧客のために短期間の許可リストを追加。\n- グローバルな制限を下げるのではなく、リスクのある特定ルートを締める。\n- 共有ネットワークをブロックしないために強い識別(API キー必須、IP 依存を減らす)を有効にする。\n- サンプルを取得:上位キー、上位IP、ユーザーエージェント、ペイロードパターン。\n\n顧客のために上限を上げる前に、その顧客の通常のリクエストパターン、エンドポイントの構成、バッチ化やバックオフが可能かを確認し、キー共有をしていないかを確かめてください。\n\n月次レビューでは:上位で制限にかかるエンドポイント、トラフィックに対する制限ヒット率、高コスト新規ルート、クオータが実利用に合っているかをチェックします。\n\n## 例:実際のパブリックAPIをユーザーを壊さずに守る\n\nあなたが運営するパブリックAPIが、顧客ポータル(高ボリューム、安定したトラフィック)と内部管理ツール(低トラフィックだが強力な操作)で使われていると想像してください。両方とも API キーを使い、ポータルはエンドユーザー向けにログインエンドポイントも持っています。\n\nある午後、パートナーがバグのある統合を出荷します。失敗したリクエストを短時間で再試行するループが発生し、単一の API キーから毎秒 200 リクエスト送られ始めます。ガードレールがなければ、そのキー一つで他のすべてを圧迫してしまいます。\n\nキー単位の制限があれば影響範囲は抑えられます。問題のキーが分単位の上限に達して 429 を受け取り、他の顧客は通常通り動作し続けます。さらにエクスポートのような高コストなエンドポイントには別に低い上限を設けておけば、「許可された」トラフィックであってもデータベースを過負荷にすることはできません。\n\n同時に、認証エンドポイントに対する総当たり攻撃が始まったとします。共有IPレンジ全体をブロックする代わりに、その挙動に合わせて遅延を入れ、アカウントあたりの失敗試行数と短いウィンドウの IP ごとの指標に基づいて段階的にロックアウトします。攻撃者は次第に長い待ち時間を受け、最終的に一時的にロックされます。\n\n誤ってパスワードを数回間違えた実在の顧客は回復できます。あなたのレスポンスが明確で予測可能だからです:\n\n- Retry-After を含む 429 でクライアントがいつ再試行できるかが分かる\n- 短いロックアウト(例えば 10〜15 分)で恒久的な禁止ではない\n- アカウントの存在を漏らさない一貫したエラーメッセージ\n\n対応の確認には以下のメトリクスを見ます:\n\n- API キーとエンドポイントごとの 429 発生率\n- 認証失敗率とロックアウト数\n- インシデント時の P95 レイテンシと DB CPU 使用率\n- 影響を受けたユニークキー数(小さくあるべき)\n\nこれが、バックエンドを守りながら通常のユーザーを罰しない保護的なレート制限の例です。\n\n## 次のステップ:小さなポリシーを作って反復する\n\n初日から完璧なモデルは不要です。小さく明確なポリシーを始めて、実際のユーザーの挙動を学びながら改善してください。\n\nしっかりした最初のバージョンは通常次の3つを含みます:\n\n- ほとんどのエンドポイントをカバーするキー単位のベースライン(分あたりリクエスト数)\n- 高コストエンドポイント(検索、エクスポート、ファイルアップロード、複雑なレポート)への厳しい上限\n- クライアントに次の行動を示す短いメッセージを含む明確な 429 レスポンス\n\nロックアウトは不正リスクが高く意図が推測しやすい場合にのみ導入します。サインアップ、ログイン、パスワードリセット、トークン作成などが典型的な候補です。ロックアウトは最初は短めに(分単位)、段階的な摩擦を優先:遅延、短期ブロック、その後に強いチェックを要求する、という順序にします。\n\nサポートがエンジニアの助けなしに説明できるよう、ポリシーを平易な言葉で文書化してください。何を制限するか(API キーごと、IP ごと、アカウントごと)、リセットウィンドウ、顧客の回復方法を含めます。\n\n新しいバックエンドを実装する際にこれをやるなら、AppMaster は実用的な選択肢になり得ます:API を作り、カウンタやロックアウト判定を含むビジネスワークフローを視覚的に定義してクラウドにデプロイしたり、必要に応じて生成されたソースコードをエクスポートして完全な制御を得ることができます。

始めやすい
何かを作成する 素晴らしい

無料プランで AppMaster を試してみてください。
準備が整ったら、適切なサブスクリプションを選択できます。

始める