---
title: "APIレート制限（レートリミット）とは？5方式の比較と429設計・分散実装【2026年版】"
url: "https://www.issoh.co.jp/tech/details/16179/"
published: 2026-08-05
updated: 2026-10-30
categories: ["アーキテクチャ"]
publisher: "株式会社一創"
---

# APIレート制限（レートリミット）とは？5方式の比較と429設計・分散実装【2026年版】

1つのクライアントが毎秒500回APIを呼び、他の利用者のレスポンスが軒並み遅くなる。この種の障害をサーバー増強ではなく入口の制御で止める仕組みが、レートリミット（レート制限）です。APIに対して課すものを特にAPIレート制限と呼び、公開APIの多くが「1時間あたり何回まで」といった上限を利用規約やドキュメントで明示しています。本記事では制限単位の決め方、5方式のアルゴリズムの挙動差、429と503の返し分け、Redisで分散カウンタを原子的に扱う実装、外部APIの上限に当たった利用側の再送処理、アクセスログからしきい値を逆算する手順までを実装者の目線でまとめました。nginx・Redis・Pythonの設定例とコードも載せています。DDoS防御やサーキットブレーカーとの守備範囲、導入を見送るべき条件も条件付きで示します。

## まとめ：レートリミットの選定方針としきい値決定の結論

レートリミットは、単位時間あたりのリクエスト数に上限を設けて、1つのクライアントによる占有と誤実装の暴走を入口で止める仕組みです。守るのは可用性と公平性の2点で、悪意ある大量トラフィックの遮断はWAFやDDoS防御の担当になります。APIレート制限とは何かを一言で言えば「API提供者が利用者ごとに決めた、呼び出し回数の天井」で、提供側は守るために課し、利用側はその天井を前提に呼び出し方を設計します。

アルゴリズムは用途で決まります。バースト（瞬間的な集中）を許したい公開APIならトークンバケット、下流を一定ペースで守りたいならリーキーバケット、実装を急ぐ社内APIなら固定ウィンドウカウンタで足ります。固定ウィンドウは窓の境界で上限の2倍が通るため、決済や認証など超過が実損につながる経路には向きません。

しきい値は勘で置きません。アクセスログのクライアント別リクエスト数から分位点を出し、p99.9の3〜5倍を上限に、平常時の最大瞬間値を包含する幅をバーストへ割り当てます。導入時は監視のみのドライラン期間を挟み、遮断対象が想定と一致してから本適用へ切り替えてください。外部APIを呼ぶ側に立つときは、`Retry-After`と残数ヘッダを読んで待つ再送処理を最初から組み込むのが前提になります。

## レートリミットの定義と制限単位｜スロットリング・クォータとの境界

### リクエスト数を時間窓で区切って制限する仕組みと導入する3つの目的

レートリミットは「識別子ごとに、一定時間内で受け付けるリクエスト数の上限を決め、超えた分を拒否または遅延させる」制御です。毎秒10リクエスト、1時間あたり5,000リクエストといった形で表現し、上限に達したクライアントにはHTTPのエラーステータスを返します。

導入する目的は3つ。1つ目は可用性の維持で、特定クライアントの暴走がデータベース接続やワーカースレッドを食い潰す事態を防ぎます。2つ目は公平性の確保。無料プランの利用者が有料プランの応答時間を悪化させる構図を断ちます。3つ目はコスト制御で、従量課金の外部APIや生成AIの推論を挟む経路では、上限がそのまま請求額の天井として効くのです。

3つの目的に加えて、番号を変えながら照会を繰り返す列挙攻撃の速度を落とす防御の役目もあります。2026年10月には、NP後払いの請求書再発行システムに機械的かつ連続的なリクエストが行われ、28,884件の取引の氏名・住所にアクセスされた事案が公表されました。照会窓口に回数制限を置く設計は[NP後払いの不正アクセス：2.9万件の対象確認と窓口、請求書再発行の影響](https://www.issoh.co.jp/tech/details/19079/)でPythonの実装例とあわせて解説しています。

### APIレート制限とは何か｜提供側が課す上限と利用側が受ける上限の違い

APIレート制限という言葉は、立場によって指すものが変わります。API提供側にとっては「自社APIへ設定する上限と、その判定の仕組み」です。一方、外部APIを呼ぶ利用側にとっては「相手が決めた上限と、超えたときに返ってくる応答」を指します。検索でこの語を調べる人の多くは、後者の立場で429エラーに遭遇した開発者でしょう。本記事は両方を扱います。

提供側の具体例を2つ挙げます。GitHubのREST APIは、未認証で毎時60リクエスト、個人アクセストークンで毎時5,000リクエストを上限とし、GitHub Enterprise Cloudの組織が所有するGitHub App経由では毎時15,000リクエストへ引き上げています（[GitHub公式ドキュメント「Rate limits for the REST API」](https://docs.github.com/en/rest/using-the-rest-api/rate-limits-for-the-rest-api)・2026年10月1日確認）。AWSのAPI Gatewayは、アカウント・リージョン単位で毎秒10,000リクエストを既定の上限とし、トークンバケットの容量5,000リクエストぶんのバーストを別に認めています。ケープタウンやミラノなど一部リージョンでは既定が毎秒2,500リクエスト・バースト1,250に下がる点も明記されています（[Amazon API Gateway quotas](https://docs.aws.amazon.com/apigateway/latest/developerguide/limits.html)・2026年10月1日確認）。

利用側が押さえるべき点は、上限が1種類とは限らないことです。GitHubは回数の上限とは別に二次レート制限を設け、AWSは「スロットリングとクォータはベストエフォートで適用され、保証された上限ではなく目標値として扱うべき」と説明しています（[API Gatewayのスロットリング解説](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-request-throttling.html)）。公開値ぎりぎりまで使う設計にせず、上限の7〜8割で頭打ちにする余裕を利用側でも持っておくと安全です。

### 制限単位の設計｜IPアドレス・APIキー・ユーザーIDの使い分け

何を1クライアントと数えるか。この定義が設計の出発点になります。IPアドレスは認証前のエンドポイントで唯一使える識別子ですが、企業のNAT配下やモバイルキャリアのCGNATでは数千人が同一IPを共有するため、単独で厳しい上限を課すと正規利用者を巻き込みます。ログイン試行の回数制限では、IPとアカウント名の組み合わせを併用する形が実務的です。反対に、送信元を多数のIPへ散らした正規形式の大量照会はIP単位の上限では止まらず、ログイン後のアカウント単位で数える必要があります。実例は[アフラックの情報漏洩440万人｜大量照会を止められなかった原因と照会量制御の実装](https://www.issoh.co.jp/tech/details/18136/)で解説しました。

認証後はAPIキーやトークンに紐づく契約単位で数えます。さらにエンドポイント単位で上限を分けると精度が上がるのです。一覧取得は毎分600回、レポート生成は毎分5回、といった具合になります。一覧取得の上限は、ページ送りを繰り返して会員表の全件を取り出す使われ方への歯止めにもなります。返した行数から全件規模の取得を検知するSQLは[焼肉きんぐの不正アクセスと1,078万件の会員情報](https://www.issoh.co.jp/tech/details/18134/)で示しました。処理コストが2桁違うエンドポイントを同一の上限で括ると、軽い処理には緩すぎ、重い処理には甘すぎる値にしかなりません。

### スロットリング・クォータ・輻輳制御との用語上の重なりと実務での違い

スロットリングは超過分を即座に拒否せず遅延させて流量を均す挙動で、レートリミットの実装手段の1つとして語られる用語です。クォータは月間100万リクエストのように、より長い期間の総量に対する割り当てを指します。毎秒の上限と月間総量を同時に課す設計が一般的で、両者は排他ではありません。AWS API Gatewayの使用量プランも、毎秒のスロットリングと日・週・月単位のクォータを別の設定項目として持っています。輻輳制御はTCPの層で送信側が混雑を検知して送出量を調整する仕組みなので、層も主体も別物です。課金連動まで含めるなら[API管理の構成要素](https://www.issoh.co.jp/tech/details/13795/)の側で整理してください。

## アルゴリズム5方式の比較表｜精度・メモリ量・バースト許容と適用先

### 固定ウィンドウカウンタの実装コストの低さと境界で上限2倍が通る欠点

固定ウィンドウカウンタは、時刻を固定長の窓に区切り、窓ごとのカウンタを加算するだけの方式です。キーは「識別子と窓の開始時刻」の組み合わせで、実装はカウンタの加算と有効期限の設定で済みます。メモリはクライアント1つにつき整数1個。導入コストは5方式で最も低く抑えられます。

弱点は窓の境界にあります。毎分60リクエストの上限で、あるクライアントが10時00分59秒に60回、10時01分00秒にさらに60回送ると、実質2秒間で120リクエストが通過してしまうのです。認証試行やクーポン発行のように、超過が金銭や不正に直結する経路では選ばないほうが安全でしょう。

### スライディングウィンドウログとカウンタ近似におけるメモリ消費の差

スライディングウィンドウログは、リクエストごとのタイムスタンプを保持し、現在時刻から窓長を引いた時点より古い記録を捨てて残数を数えます。境界の抜けは発生しません。代償はメモリで、消費量が保持中の件数に比例します。毎分1万リクエストを許すクライアントが1,000社いれば、1,000万件分のタイムスタンプを常時抱える計算です。

スライディングウィンドウカウンタは、前の窓と現在の窓の2つのカウンタを持ち、窓内の経過割合で前窓の値を重み付けして加算する近似方式になります。現在の窓が40%経過した時点なら、前窓の値の60%と現窓の値を足して判定する仕組みです。メモリは整数2個、境界の2倍問題も実用上は消えます。多くの公開APIでは、この近似が現実的な落としどころです。

### トークンバケットとリーキーバケットでバースト扱いが分かれる理由

トークンバケットは、容量の決まったバケツに一定レートでトークンを補充し、リクエスト1件につき1枚消費する方式です。しばらく無通信だった利用者はトークンを貯め込めるので、容量ぶんのバーストを一度に通せます。補充レートが平均流量、容量が許容バーストという2つのパラメータで挙動を表現でき、利用パターンが読めない公開APIやSDKに向いている方式です。前述のAWS API Gatewayもこの方式で、使用量プランの「レート」がトークンの補充速度、「バースト」がバケツの容量に対応します。

リーキーバケットは逆に、流入をキューへ溜めて一定レートで漏らす方式です。出力レートが常に一定になるため、下流のデータベースやバッチ処理を守る目的に適します。nginxの`ngx_http_limit_req_module`はこの方式で、`limit_req_zone`で毎秒のレートを、`limit_req`の`burst`で待ち行列の長さを指定します（[nginx公式ドキュメント](https://nginx.org/en/docs/http/ngx%5Fhttp%5Flimit%5Freq%5Fmodule.html)・2026年10月1日確認）。判断は単純です。クライアント体験を優先するならトークンバケット、下流保護を優先するならリーキーバケットを選びます。

### 実装コスト・精度・メモリ量から5方式を横並びで比較した早見表

5方式の性質を1つの表にまとめます。選定では精度そのものより「境界の抜けが業務上許容できるか」を先に見ると迷いが減ります。

| 方式        | 精度       | メモリ    | バースト    | 向く用途        |
| --------- | -------- | ------ | ------- | ----------- |
| 固定ウィンドウ   | 低（境界で2倍） | 整数1個   | 制御不可    | 社内API・暫定導入  |
| スライディングログ | 高（抜けなし）  | 件数に比例  | 不可      | 厳格な上限が要る経路  |
| スライディング近似 | 中〜高      | 整数2個   | ほぼ不可    | 一般的な公開API   |
| トークンバケット  | 中        | 数値2個   | 容量ぶん許容  | SDK・外部提供API |
| リーキーバケット  | 中        | キュー長ぶん | 平滑化して吸収 | DB・バッチの下流保護 |

## 429レスポンスとRateLimitヘッダの設計｜Retry-Afterの返し方

### 429と503の使い分け｜nginxのlimit\_req\_statusは既定で503

上限超過で返すステータスは429 Too Many Requests（[RFC 6585](https://www.rfc-editor.org/rfc/rfc6585.html) 第4節で定義）が正解です。同節は429の応答に再試行までの待ち時間を示す`Retry-After`を含めてよいとし、429の応答をキャッシュに保存してはならないとも定めています。利用者の識別方法や数え方は規定していません。503 Service Unavailableはサーバー側の一時的な過負荷や保守を意味し、クライアントから見ると「自分の送りすぎ」なのか「サーバーの不調」なのか区別がつきません。

ここに実装上の落とし穴があります。nginxの`limit_req_status`の既定値は`503`で、設定を書き足さないかぎり429は返りません（nginx公式ドキュメント・2026年10月1日確認）。ゲートウェイでレート制限を有効にしただけで429が返ると思い込んでいると、クライアントのリトライ実装が過負荷用の分岐に流れます。設定ファイルで`limit_req_status 429;`を明示してください。

### nginxで429を返しバーストとドライランを設定する最小構成の設定例

クライアントIPごとに毎秒10リクエスト、バースト20を許し、超過時に429を返す最小構成です。導入初期は`limit_req_dry_run on;`で遮断せず記録だけを取り、ログを確かめてから外します。ドライランは1.17.1で追加されたディレクティブで、有効時は流量を制限せず、超過数だけを共有メモリゾーンへ記録します。

```
http {
    # 1クライアントIPあたり毎秒10リクエスト。状態は10MBの共有メモリに保持する
    limit_req_zone $binary_remote_addr zone=api_per_ip:10m rate=10r/s;

    server {
        location /api/ {
            # 20件までの超過は待たせずに通し、それを超えたら拒否する
            limit_req zone=api_per_ip burst=20 nodelay;
            # 既定の503ではなく429を返す
            limit_req_status 429;
            # 拒否ログの重要度（既定はerror）
            limit_req_log_level warn;
            # 導入初期のみ有効化し、遮断せずに記録だけ取る
            limit_req_dry_run on;
        }
    }
}
```

`nodelay`を付けないとバースト分は待ち行列で遅延させられ、応答時間が伸びます。公開APIではクライアントに待たせるより早く429を返すほうが扱いやすいため、`nodelay`付きが無難です。なお、同モジュールの説明に`Retry-After`を自動で付与する記述はありません。待機秒数を伝えたい場合は、ゲートウェイ製品の機能かアプリケーション側で付けます。

### RateLimitヘッダの現状｜IETFドラフト版とX-接頭辞の慣用実装

残数をクライアントへ知らせるヘッダは標準化の途中にあります。IETFのhttpapiワーキンググループが進める[draft-ietf-httpapi-ratelimit-headers](https://datatracker.ietf.org/doc/draft-ietf-httpapi-ratelimit-headers/)は2026年5月23日更新の第11版が最新で、RFCとしては未発行です（datatracker・2026年10月1日確認。この版の有効期限は2026年11月24日）。この案は`RateLimit`と`RateLimit-Policy`の2フィールドを構造化フィールド構文で表現し、窓長をパラメータ`w`で秒指定します。

実務では`X-RateLimit-Limit`のような接頭辞つきの慣用ヘッダが今も広く使われています。GitHubのREST APIは`x-ratelimit-limit`、`x-ratelimit-remaining`、`x-ratelimit-used`、`x-ratelimit-reset`、`x-ratelimit-resource`を返し、未認証で毎時60、個人アクセストークンで毎時5,000という上限を公開しています。回数とは別枠で同時実行100リクエスト、REST APIで毎分900ポイント、実時間60秒あたりCPU時間90秒という二次レート制限も課しており、処理コストの重いエンドポイントを回数だけで縛らない設計です。上限を超えたときの応答は403または429のどちらかと記載されており、429だけを見て判定するクライアントは取りこぼします（公式ドキュメント・2026年10月1日確認）。自社APIでも慣用ヘッダを当面維持し、RFC発行時に新形式を併記できる実装にしておくと移行が楽になります。

### Retry-Afterの秒数指定とクライアント側の指数バックオフの実装

429を返すときは`Retry-After`を必ず添えます。値は待機秒数かHTTP-date形式で（[RFC 9110](https://www.rfc-editor.org/rfc/rfc9110.html) 第10.2.3節）、リセットまでの残り秒数を入れるのが分かりやすい実装です。これが無いと、クライアントは即座に再送して上限を踏み続けます。

クライアント側は`Retry-After`を第一に尊重し、指定が無い場合のみ指数バックオフに落とします。初回1秒、次に2秒、4秒と倍にしつつ、同時刻に再送が集中しないよう0〜1秒の乱数を足す（ジッターを入れる）実装が定番です。再送する以上、同じ操作が2回適用される可能性は残ります。決済や在庫引当のように二重実行が実損になる経路では、リクエストIDを使った[冪等性の担保](https://www.issoh.co.jp/tech/details/13382/)をセットで設計してください。

## 分散環境でのカウンタ共有｜Redisの原子性とゲートウェイ層への寄せ方

### インスタンス単位のカウントで実効上限が台数倍に膨らむ典型的な誤り

アプリケーションのメモリ上にカウンタを持つ実装は、1台構成では正しく動きます。ところが同じアプリを4台へ水平展開した瞬間、各台が独立に上限を数えるため、実効上限は設定値の4倍に膨らみます。オートスケールで台数が変動する構成なら、上限は時間帯ごとに勝手に伸び縮みする状態です。nginxの`limit_req_zone`も共有メモリはそのnginxプロセス群の内側に閉じるので、nginxを複数台並べれば同じ問題が起きます。

この誤りは負荷試験で見つかりません。試験環境が1台構成だったり、負荷生成側のIPが固定で全リクエストが同じ台に張り付いたりするからです。解決策は、分散カウンタを外部ストアへ置くか、ゲートウェイ層に制限そのものを寄せるかの二択になります。

### RedisのINCRとEXPIREを分けた際のキー永続化とLuaでの原子化

共有ストアにはRedisを使うのが一般的です。ただし`INCR`でカウンタを加算し、値が1のときだけ`EXPIRE`で有効期限を付ける2コマンド構成には落とし穴があります。`INCR`の直後にプロセスが落ちると有効期限の無いキーが残り、そのクライアントは窓が切り替わっても永久に締め出されるのです。Redis公式の[INCRコマンドの解説](https://redis.io/docs/latest/commands/incr/)も、レートリミッターのパターンとしてこの競合状態を指摘し、Luaスクリプトへまとめる修正を示しています（2026年10月1日確認）。

回避策は2つ。Luaスクリプトで加算と期限設定を1つの原子的操作にまとめるか、`SET`コマンドの`NX`と`EX`オプションでキー生成と期限付与を同時に行ってから加算します。トークンバケットのように残トークン数と最終補充時刻の2値を同時に更新する方式では、読み取りと書き込みの間に他プロセスが割り込むため、Luaによる原子化がほぼ必須になります。

### Luaスクリプトで加算と期限付与を1回で済ませる固定ウィンドウの実装例

固定ウィンドウカウンタをRedisで原子的に数える最小のスクリプトです。キーには識別子と窓の開始時刻を入れ、戻り値の現在値と残り秒数から、アプリケーション側で429の判定と`Retry-After`の値を決めます。

```
-- ratelimit.lua
-- KEYS[1]: 識別子と窓の開始時刻を連結したキー（例 rl:apikey123:202610011200）
-- ARGV[1]: 窓の長さ（秒）
local current = redis.call("INCR", KEYS[1])
if current == 1 then
  -- 窓の最初のリクエストでだけ有効期限を付ける（INCRと同じ原子的操作の中で行う）
  redis.call("EXPIRE", KEYS[1], ARGV[1])
end
local ttl = redis.call("TTL", KEYS[1])
return {current, ttl}
```

redis-cliから動作を確かめるなら、次のように呼び出します。カンマの左がキー、右が引数です。2回目以降の実行で1つ目の値が増え、2つ目の値（残り秒数）が減っていけば正しく動いています。

```
redis-cli --eval ratelimit.lua rl:apikey123:202610011200 , 60
# 1) (integer) 1
# 2) (integer) 60
```

アプリケーション側では、1つ目の値が上限を超えたら429を返し、2つ目の値をそのまま`Retry-After`へ入れます。本番では`SCRIPT LOAD`でスクリプトを登録し、`EVALSHA`で呼ぶとネットワーク転送量を抑えられます。

### ゲートウェイ層とアプリケーション層のどちらで制限をかけるかの基準

判断基準は単純です。識別子が認証前に確定するならゲートウェイ層、認証後のプランや残高に依存するならアプリケーション層に置きます。IPアドレス単位やAPIキー単位の粗い上限はゲートウェイが担い、バックエンドへ到達する前に弾けるぶん効率もよいのです。

一方で「無料プランは毎分60回、法人プランは毎分600回」のようにプラン情報の参照が要る制限は、契約情報を持つアプリケーション側で判定するほうが素直でしょう。ゲートウェイで緩い共通上限、アプリで細かいプラン別上限という二段構えが実務的な構成です。ゲートウェイが担う機能の全体像は[APIゲートウェイの役割と導入判断](https://www.issoh.co.jp/tech/details/13210/)の側で確認してください。Kong、Envoy、各クラウドのマネージドゲートウェイはいずれもレート制限をプラグインや設定で提供しており、自前実装より先に候補へ入ります。AWS API Gatewayの場合、使用量プランでAPIキーごとの上限、ステージ設定でメソッドごとの上限をかけられ、クライアント別・メソッド別・アカウント・リージョン全体の順に適用されます。APIキーと使用量プランの具体的な設定は[API GatewayのAPIキーと使用量プランの設定手順](https://www.issoh.co.jp/tech/details/18491/)で扱っています。

## APIレート制限に当たった利用側の対処｜残数ヘッダの確認と再送の実装

### curlでレスポンスヘッダを読み上限値・残数・リセット時刻を確かめる

外部APIを呼ぶ側に立ったら、まず相手が返すヘッダで自分の上限と残数を確かめます。GitHubの場合は次のコマンドで確認できます。`-I`でヘッダだけを取り出し、`x-ratelimit`で始まる行を抜き出す操作です。

```
curl -sI https://api.github.com/rate_limit | grep -i x-ratelimit
# x-ratelimit-limit: 60
# x-ratelimit-remaining: 59
# x-ratelimit-reset: 1790000000
# x-ratelimit-resource: core
# x-ratelimit-used: 1
```

出力例は未認証で実行した場合の形で、数値は実行時点で変わります。`x-ratelimit-reset`はUNIX時刻（秒）で、この時刻に残数が上限まで戻ります。ドキュメントに上限値が書かれていないAPIでも、応答ヘッダを見れば実際の値が分かる場合は多いのです。ヘッダ名はAPIごとに違うので、`ratelimit`や`retry`を含む行を広めに抜き出すと見落としが減ります。

### 外部APIの429を受けたときにRetry-Afterを読んで待つPythonの再送処理

再送処理は「`Retry-After`があればそれに従う、残数が0ならリセット時刻まで待つ、どちらも無ければ指数バックオフ」の3段で組みます。GitHubの[REST APIのベストプラクティス](https://docs.github.com/en/rest/using-the-rest-api/best-practices-for-using-the-rest-api)も、`retry-after`があれば従い、`x-ratelimit-remaining`が0なら`x-ratelimit-reset`の時刻まで待ち、どちらも無ければ少なくとも1分待ってから指数的に間隔を広げるよう案内しています（2026年10月1日確認）。次の例はrequestsライブラリを使った実装です。

```
import random
import time

import requests

def get_with_retry(url, headers=None, max_attempts=5):
    """レート制限（429・403・503）を受けたら待機して再送する"""
    resp = None
    for attempt in range(max_attempts):
        resp = requests.get(url, headers=headers, timeout=10)
        if resp.status_code not in (403, 429, 503):
            return resp

        retry_after = resp.headers.get("Retry-After")
        remaining = resp.headers.get("x-ratelimit-remaining")
        reset = resp.headers.get("x-ratelimit-reset")

        if retry_after and retry_after.isdigit():
            # 1. サーバーが指定した秒数だけ待つ
            wait = int(retry_after)
        elif remaining == "0" and reset:
            # 2. 残数が0ならリセット時刻（UNIX秒）まで待つ
            wait = max(int(reset) - int(time.time()), 1)
        elif resp.status_code == 403:
            # 403かつレート制限の手掛かりが無ければ権限エラーとして再送しない
            return resp
        else:
            # 3. 手掛かりが無ければ指数バックオフにジッターを足す
            wait = (2 ** attempt) + random.uniform(0, 1)
        time.sleep(wait)
    return resp
```

403を対象に含めているのは、GitHubのように上限超過で403を返すAPIがあるためです。ただし403は本来の権限エラーでも返るので、レート制限の手掛かりが無い403は再送せずに返します。バックオフの初期値は相手のドキュメントに合わせて調整してください。GitHubの二次レート制限を相手にするなら、1回目の待機を60秒以上に置くのが案内どおりの実装です。`Retry-After`がHTTP-date形式で来るAPIを相手にするなら、`email.utils.parsedate_to_datetime`で日時へ変換してから待機秒数を計算してください。

### 上限に当たり続ける場合の打ち手｜キャッシュ・一括取得・上限引き上げ申請

再送処理を入れても頻繁に429が返るなら、呼び出し回数そのものを減らします。打ち手は3つです。1つ目は応答のキャッシュで、変化の少ないマスタ情報を毎回取りに行かない。GitHubは条件付きリクエスト（`If-None-Match`）で304が返った場合、認証済みなら上限を消費しないとしています。2つ目は一括取得で、1件ずつのループをページあたりの件数を増やした一覧取得や一括APIへ置き換える方法です。3つ目は上限の引き上げで、AWS API Gatewayのアカウント上限のようにサービスクォータの申請で上げられるものもあります。

複数のワーカーから同じAPIキーで呼んでいる場合は、利用側にもレート制限が要ります。各ワーカーが独立に全力で呼ぶと、上限を合算で踏み抜くからです。前章のRedisスクリプトを自分の送信側に置き、APIキー単位で送出量を数えれば、相手の上限の手前で自ら止まれます。上限を複数の送信元で分け合う構成は、提供側の分散カウンタと同じ考え方で組めます。

## しきい値の決め方｜正常利用の実測分位点から上限とバーストを逆算

### アクセスログからクライアント別リクエスト数の分位点を求める手順

上限値を勘で決めると、緩すぎて意味がないか、厳しすぎて正規利用者を切るかのどちらかです。実測から逆算してください。

1. 直近30日のアクセスログを、制限単位（APIキーやIP）とエンドポイントで分類する
2. 1分あたりのリクエスト数を時系列で集計し、クライアントごとの系列を作る
3. 全クライアント横断でp50・p95・p99・p99.9と最大値を求める
4. 上位の外れ値がどのクライアントかを特定し、正規利用か暴走かを個別に確認する

手順4を飛ばさないでください。分位点の上端は、たいてい特定の1社か1つのバッチ処理によるものです。正規の業務なら上限に含め、実装ミスによる無限ループなら除外して分位点を取り直します。流量の計測指標は[REDメソッドによる流量・失敗・所要時間の設計](https://www.issoh.co.jp/tech/details/15718/)と揃えておくと、導入後の監視にそのまま使えます。

### p99.9の数倍を上限に置く根拠と誤検知を避けるバースト幅の決め方

上限値はp99.9の3〜5倍を初期値に置きます。p99.9は「1,000分の1の頻度でしか起きない流量」なので、ここを直接上限にすると月に数回は正規利用者を弾く計算です。3〜5倍の余裕があれば、正常な業務ピークを通しつつ桁違いの暴走だけを捕まえられます。

バースト幅は分位点ではなく最大瞬間値から決めます。1秒粒度で集計した平常時の最大値を包含する幅をトークンバケットの容量へ割り当てれば、日次バッチの開始直後のような正常な集中で誤検知しません。目安は平均レートの10〜30秒ぶんです。平均レートと同程度まで絞ると、リトライが一斉に戻った瞬間に正規利用者を巻き込みます。

### 段階導入の順序｜計測のみのドライラン期間から本適用へ切り替える基準

いきなり遮断を有効にしてはいけません。まず「上限を超えたクライアントをログに記録するだけで通す」ドライランモードで2週間動かします。nginxなら前述の`limit_req_dry_run on;`がこの用途のディレクティブです。記録された一覧に想定どおりの相手だけが並んでいるかを確認してください。社内バッチや監視ツールが混じっていたら、別の制限単位へ切り出すか上限を引き上げます。

本適用への切り替え基準は2つ。超過クライアントのうち正規利用者が占める割合が1%を下回っていること。そして超過時のレスポンス処理を主要な社内クライアントが実装済みであること。満たさないまま遮断へ切り替えると、問い合わせ対応で運用が止まります。

## DDoS対策・サーキットブレーカーとの守備範囲｜導入を見送る条件

### レート制限とWAF・DDoS防御が受け持つトラフィック層の違い

レート制限は、識別可能な正当なクライアントが送りすぎる状況を想定した仕組みです。数万の送信元から同時に押し寄せるボリューム型攻撃は、アプリケーションへ到達する前に落とす必要があります。ネットワーク層と輸送層の大量トラフィックはCDNやDDoS防御サービスの担当で、レート制限が肩代わりすることはできません。

逆に、正しいAPIキーを持つ利用者が誤ってループ処理を回した場合、WAFのシグネチャには何も引っかかりません。攻撃パターンではなく流量そのものが問題だからです。両者は直列に並ぶ層で、CDNとDDoS防御を外側に、レート制限をアプリケーションの入口へ置く構成が基本形になります。

### サーキットブレーカーとの併用｜自衛と下流保護で役割を分ける設計

同じ「流量を絞る」仕組みでも、レート制限とサーキットブレーカーは向きが逆です。レート制限は自分に入ってくる量を制限する入口の防御、サーキットブレーカーは呼び出す先の障害を検知して呼び出しを止める出口の防御になります。実装上は両方を入れるのが正解です。入口で流量を抑え、出口で下流の異常時に素早く諦める。この2つが揃って初めて障害が横に伝播しない構成になります。連鎖障害を止める側の実装は[サーキットブレーカーの仕組みと導入判断](https://www.issoh.co.jp/tech/details/13216/)にまとめてあります。

### レート制限の導入を見送るべき3条件と運用で頻発する失敗パターン

導入しないほうがよい場面を3つ挙げます。1つ目は、クライアントが社内システムに限られ、呼び出し元のコードを自分たちで管理できる場合。上限を課すより呼び出し側の実装を直すほうが早く確実です。2つ目は、サーバーレスの従量課金上限が別途効いていてコスト面の天井が既にある場合。3つ目は、1日数千件規模で暴走しても容量に届かない社内向け管理画面になります。

運用で頻発する失敗は3つです。管理者アカウントや監視ツールを制限対象から除外し忘れて障害検知が止まる。ヘルスチェックのエンドポイントに制限がかかりロードバランサが全台を切り離す。そして超過ログを残さないため、問い合わせを受けても遮断か別障害か判別できない。3つ目が最も後を引きます。超過時は識別子・エンドポイント・上限値・実測値の4点を必ずログへ出してください。

### 受託開発でレート制限をAPI仕様に組み込む際に合意すべき3項目

外部の開発会社とAPIを作る場合、レート制限は仕様書に書かれないまま実装フェーズへ流れがちです。発注時点で3項目を決めておくと後戻りが減ります。制限単位（契約単位かIP単位か）、上限超過時の挙動（429で拒否するか遅延させるか）、そしてクライアント側のリトライ実装の責任範囲です。3つ目が曖昧なまま納品されると、サーバーは正しく429を返すのに利用側が即座に再送し続ける、という噛み合わない構成になります。上限値と返すヘッダは、エラー応答の定義と並べて[API設計書の記載項目](https://www.issoh.co.jp/tech/details/4068/)へ書き込んでおくと、実装者と利用者の認識がずれません。API設計から上限値の根拠づけ、ゲートウェイ選定までを含めた開発を検討するなら、[API開発・システム連携の支援内容](https://www.issoh.co.jp/service/system/api/)をご確認ください。

## よくある質問

レートリミットの設計や運用でよく寄せられる疑問を5つ取り上げます。

### APIレート制限とレートリミットは同じ意味ですか？

同じ仕組みを指します。英語のrate limitingに対して、レートリミット、レート制限、流量制限といった訳語が併存している状態です。APIに対して課すものを特にAPIレート制限と呼びます。日本語の資料では「レート制限」、ヘッダ名やライブラリ名では「rate limit」が使われる傾向があります。API仕様書では表記をどちらかに統一してください。

### 上限超過時は429と503のどちらを返すべきですか？

429を返してください。503はサーバー側の一時的な過負荷や計画停止を表すため、クライアントから見て原因の切り分けができません。注意点として、nginxの`limit_req_status`は既定が`503`で、設定を書き足さないと429になりません。製品ごとに既定値が異なるので、導入時に実際のレスポンスを確認してください。

### レート制限をかけたら正規ユーザーからのエラー報告が増えました。原因は？

まず制限単位を疑ってください。IPアドレス単位で数えていると、企業のNAT配下から接続する複数の従業員が1クライアントとして合算されます。次に上限値の根拠です。分位点を取らずに切りのよい数字を置くと、平常時のピークを下回ることがよくあります。最後にバースト幅で、日次バッチによる瞬間的な集中を吸収できる容量があるかを見てください。

### 外部APIのレート制限に当たって429が返ります。どう直せばよいですか？

まず応答の`Retry-After`と残数ヘッダを確認し、指定された時間だけ待ってから再送する処理を入れます。指定が無ければジッター付きの指数バックオフで待ちます。それでも頻繁に当たるなら、応答のキャッシュ、一括取得APIへの置き換え、複数ワーカー間での送出量の共有で呼び出し回数を減らしてください。有料プランやクォータ申請で上限を引き上げられるAPIもあります。

### GraphQL APIでもリクエスト数で制限してよいですか？

リクエスト数だけでは足りません。[GraphQL](https://www.issoh.co.jp/tech/details/2924/)は1リクエストで取得するフィールド数やネストの深さを利用者が決められるため、同じ1回でも処理コストが数百倍変わります。クエリの複雑度を事前に算出してポイントとして数え、時間あたりのポイント上限で縛る方式が一般的です。GitHubもGraphQL APIのエンドポイントに毎分2,000ポイントというコストベースの二次レート制限を課しています。

## 関連記事

- [Kong Gatewayとは](https://www.issoh.co.jp/tech/details/4483/)：ゲートウェイ層でレート制限を組む際の設定単位を確認できます
- [DDoS攻撃とは](https://www.issoh.co.jp/column/details/13260/)：レート制限の外側に置く防御層の担当範囲を整理しています
- [Webhookの実装方法と作り方](https://www.issoh.co.jp/tech/details/1378/)：送信側として上限に当たった場合の再送設計に使えます
- [非同期処理とは](https://www.issoh.co.jp/tech/details/13590/)：超過分をキューへ逃がす構成を検討する際の前提知識です
- [バージョニングとは](https://www.issoh.co.jp/tech/details/13488/)：上限値を変更する際の互換性の扱いを判断できます
- [nimoca不正アクセス：届いたメールの真偽と521件の範囲、番号と生年月日で照会する機能のBot対策](https://www.issoh.co.jp/tech/details/18789/)：IPを分散されても効く、カード番号単位の試行上限の実例です

---

出典: [APIレート制限（レートリミット）とは？5方式の比較と429設計・分散実装【2026年版】](<https://www.issoh.co.jp/tech/details/16179/>)（株式会社一創）
