LLMサービスの利用者ごとの上限設計:回数・トークン・同時実行をどう制限するか
AIを使いこなすClaudeで執筆し、GPTで自動校閲・修正しています。

結論から言うと、利用者ごとの上限は「短時間の速度はトークンバケット、期間の総量は月次(または日次)のトークンクォータ、同時実行は利用者ごとのセマフォ」の3層に分けるのが基本形です。回数だけで縛るとトークン消費の大きいリクエストを防げず、トークンだけで縛ると短時間に集中するアクセスを防げません。3つの軸を別々の目的で持ち、料金プランごとに数値を変えます。 この前提には理由があります。LLM提供元の上限は、利用者ではなく組織やプロジェクトに対して掛かります。OpenAIはレート制限のガイドで、制限が組織とプロジェクトの単位で動くと説明しています。GeminiのAPIもプロジェクト単位で、APIキー単位ではありません。つまり、1人のヘビーユーザーが上流の枠を使い切ると、同じ枠を共有する他の利用者も429を受ける可能性があります。エンドユーザー単位の公平性は、自分で作る必要があります。 この記事では、方式の比較表、プラン別の上限設計シート、上流上限との照合手順の順に示します。数値はすべて「説明用の例」で、実測値ではありません。
3つの軸は守るものが違う
- 回数、守るもの:短時間の連打、スクリプトによる乱用、典型的な単位:1分あたりのリクエスト数
- トークン、守るもの:原価、上流のトークン上限、典型的な単位:1分あたり、月あたりのトークン数
- 同時実行、守るもの:自社サーバーの接続数、上流への急な負荷増、典型的な単位:利用者ごとの処理中リクエスト数
上流側の事情も、この分け方を支持します。OpenAIはRPM(分あたりリクエスト数)、TPM(分あたりトークン数)、RPD(日あたりリクエスト数)などのうち、先に尽きたものが制限として働くと説明しています。AnthropicもMessages APIの制限をRPM、入力トークン毎分(ITPM)、出力トークン毎分(OTPM)で測ります。自社の利用者向け上限も、回数とトークンの両方を持つほうが上流の測り方と対応します。
同時実行は、上流のドキュメントに「同時実行数の上限」が明記されていなくても必要です。OpenAIは、RPMやTPMの範囲内でもトラフィックの急増でslow_downの429が出うると述べ、Anthropicも、毎分の上限がより短い時間単位で適用され、短いバーストで制限に達しうると説明しています。1人が大量に並列で投げる使い方を抑えれば、この種の急増を減らせます。
制限方式の比較表
次の表は、一般的なアルゴリズムの性質を整理した編集上の比較です。
- 固定窓、仕組み:1分や1日ごとにカウンタをリセット、長所:実装が最も簡単、残量を説明しやすい、短所:窓の境目で最大2倍近いバーストが通る、向く用途:日次・月次の回数枠
- スライディングウィンドウ(ログ)、仕組み:直近N秒のリクエスト時刻を保持、長所:正確、短所:保存量が増える、向く用途:高価なモデルの厳密な回数制限
- スライディングウィンドウ(カウンタ近似)、仕組み:前窓と今窓の重み付き合計、長所:軽く、境目の問題を和らげる、短所:近似値になる、向く用途:一般的な毎分制限
- トークンバケット、仕組み:一定速度で補充、容量まで貯まる、長所:短いバーストを許しつつ平均を抑える、短所:容量と補充速度の2つを決める必要がある、向く用途:チャット型の毎分制限、トークン速度の制限
- リーキーバケット、仕組み:一定速度で処理し、あふれたら拒否または待機、長所:出力が平らになる、短所:待ち行列の管理が要る、向く用途:上流へ平らに流したい非同期処理
- 同時実行セマフォ、仕組み:処理中の数を上限で管理、長所:ストリーミングや長い処理に有効、短所:完了処理の漏れで枠が残る、向く用途:利用者ごとの並列数
- 期間クォータ、仕組み:月次・日次の累計を加算、長所:料金プランと直結、短所:超過時の体験設計が必要、向く用途:プランの総量
Anthropicは上流の制限にトークンバケットを使い、容量は固定間隔でリセットされず継続的に補充されると説明しています。利用者向けの毎分制限も同じ方式にそろえると、上流の挙動と近くなり、説明もしやすくなります。
料金プラン別の上限設計シート
次は、チャット型サービスを想定した説明用の例です。値は自社の原価と上流の上限から置き換えてください。
- 月間トークン枠(入力+出力)、Free:200,000、Standard:3,000,000、Pro:15,000,000
- 日次リクエスト上限、Free:30、Standard:300、Pro:1,000
- バケット容量(リクエスト)、Free:3、Standard:10、Pro:20
- 補充速度(リクエスト/分)、Free:3、Standard:10、Pro:20
- 出力トークン持続速度(/分)、Free:300、Standard:1,500、Pro:4,000
- 出力トークンのバケット容量、Free:1,024、Standard:3,000、Pro:8,192
- 同時実行数、Free:1、Standard:2、Pro:4
- 1回の最大入力トークン、Free:4,000、Standard:16,000、Pro:64,000
- 1回の最大出力トークン、Free:512、Standard:1,024、Pro:2,048
- 超過時の挙動、Free:429、制限の種類に応じた待機を案内、Standard:429、制限の種類に応じた待機を案内、Pro:429、制限の種類に応じた待機を案内
設計の順序は次のとおりです。
- 月間トークン枠を、プラン価格から原価を逆算して決めます。入力・出力・キャッシュ・モデルごとの単価差があるため、単純な合計トークン数だけでは原価は決まりません。利用構成を見積もり、必要ならモデル別の枠や金額換算のクォータも設けます。
- 日次回数で、1日の呼び出し回数を抑えます。月間枠の早期消費も防ぎたい場合は、日次のトークン枠も設けます。
- バケットでバーストを調整します。容量が大きいほど許容するバーストも大きくなります。
- 出力トークン持続速度を、次節の照合で上流の枠に収まるよう調整します。
- 同時実行と1回あたりの上限で、1リクエストの大きさと並列度を抑えます。出力上限のパラメーター名はAPIに合わせます。本文のmax_tokensはその一例です。
日次リセットの時刻も決めておきます。たとえばGeminiのRPDは太平洋時間の0時にリセットされます。自社サービスでは、日次枠なら日本時間0時などのリセット時刻を、月間枠なら暦月・契約更新日・30日周期などの集計期間を決め、画面と規約に書いてそろえてください。
上流の上限との照合手順
利用者ごとの上限を合計した値が上流の枠を超えると、利用者別の制限内でも上流で拒否されます。まず持続速度の目安を次の式で確認します。
ピーク時のアクティブ利用者数 × プラン別の持続速度 の合計 ≦ 上流の上限 × 余裕率(例:0.7)
説明用の例として、上流の出力上限を100,000トークン/分、余裕率を0.7(つまり70,000)とします。ピーク時にフルに使う利用者を、Freeが60人、Standardが20人、Proが5人と仮定します。
- Free:60 × 300 = 18,000
- Standard:20 × 1,500 = 30,000
- Pro:5 × 4,000 = 20,000
- 合計:68,000(持続速度の目安では70,000以下)
仮にFreeを500にすると60 × 500 = 30,000で合計は80,000となり、余裕を超えます。この場合はFreeの速度を下げるか、上流の上限引き上げを申請するか、全員が同時にフル利用しないと見込んで超過を許容するか、のいずれかを決めます。
この計算だけでは、バケットに貯まった分の一斉消費や短時間の集中までは保証できません。RPM、入力・出力それぞれのトークン上限、モデル間の共有枠も照合し、利用者別の制限に加えて、上流の枠を共有する全体の制限と上限付き待ち行列、または拒否処理を設けます。
上流の実際の値は、各社の管理画面で確認します。Anthropicは組織ごとの上限をConsoleのRate limitsページで確認でき、ワークスペースごとに低い上限を設けることもできると説明しています。ただし、Claude Platform on AWSではワークスペース別のレート制限設定は利用できません。こうした下位の枠は、プランや用途ごとに上流の予算を分けるときに使えます。ただし、エンドユーザー単位の制限は自前で持つ必要があります。
実装で押さえる4点
1. 事前に予約し、事後に精算する。 OpenAIは、制限の計算にmax_tokensと文字数からの推定値の大きいほうを使うと説明しています。Anthropicは入力側を開始時に推定して実測で調整し、出力側は実際の生成量で数えます。自社の利用者向けクォータも、開始時に「入力の推定+最大出力トークン」を期間クォータから原子的に予約し、完了後にレスポンスの使用量で差分を精算すると、並列リクエストによる枠の超過を抑えられます。入力の推定誤差には余裕を持たせ、予約と精算はリクエストIDで管理して二重精算を防ぎます。通信切断などで使用量が不明な場合は、全額返却せず、予約を保留して確認します。max_tokensをプラン上限に抑えておく意味もここにあります。
2. 「待てば直る」と「待っても直らない」を区別する。 毎分制限の超過はRetry-Afterを付けて返し、月間枠の超過は別のエラーコードで返します。Anthropicの利用階層による月間支出上限に達した429はretry-afterヘッダーがなく、上限引き上げや翌月のリセットまで再試行しても復旧しないため、エラーコードで見分けるよう案内されています。自社APIでも、クライアントが無駄に再試行しない設計にします。
3. 画面に残量を出す。 上流は残量をレスポンスヘッダーで返します(Anthropicのanthropic-ratelimit-*、OpenAIのx-ratelimit-*)。自社でも同様に、利用者自身の残りの枠とリセット時刻を返すと、再開できる時点を判断しやすくなります。
4. 複数サーバーでは共有ストアで原子的に更新する。 次のコードは、単一プロセス内で動く、予約と精算付きトークンバケットの最小例です。未実行の説明用コードです。
import time, threading
class Bucket:
def __init__(self, capacity, refill_per_sec):
if capacity <= 0 or refill_per_sec <= 0:
raise ValueError("capacity と refill_per_sec は正数が必要です")
self.cap, self.rate = capacity, refill_per_sec
self.held = 0
self.tokens, self.ts = capacity, time.monotonic()
self.lock = threading.Lock()
def _refill(self):
now = time.monotonic()
self.tokens = min(self.cap - self.held,
self.tokens + (now - self.ts) * self.rate)
self.ts = now
def reserve(self, amount):
"""成功なら (True, 0)、不足なら (False, 再確認までの秒数)"""
if not 0 < amount <= self.cap:
raise ValueError("予約量は正数かつ容量以下が必要です")
with self.lock:
self._refill()
if self.tokens >= amount:
self.tokens -= amount
self.held += amount
return True, 0
return False, (amount - self.tokens) / self.rate
def settle(self, reserved, actual):
"""実測との差分を戻す(超過分は負債として引く)"""
with self.lock:
self._refill()
self.held -= reserved
self.tokens = min(self.cap - self.held,
self.tokens + reserved - actual)
# 例:出力 1,500 トークン/分、容量 3,000
out_bucket = Bucket(3000, 1500 / 60)
ok, wait = out_bucket.reserve(1024) # 最大出力トークン分を予約
if ok:
# ... LLM 呼び出し。使用量が確定してから一度だけ精算 ...
out_bucket.settle(1024, 380) # 実際の出力が 380 だった場合
else:
# LLM は呼び出さず、待機時間を案内して拒否
passこの例では未精算の予約分を補充の対象から外し、返却時に枠が二重に増えるのを防ぎます。その分、長い処理では補充を控えめに見積もります。返す秒数は再確認の目安で、他の処理の予約・精算によって変わります。期間クォータは補充せず別に集計し、セマフォは終了・例外時の解放と、障害時の枠回収を実装します。
複数台構成にするときは、同じ更新をRedisなどの共有ストアで原子的に実行します。複数の制限を確認する際は、一部の予約だけが残らないよう、まとめて確定するか、拒否時に取得済みの予約を取り消します。
導入前チェック
- 無料枠の乱用対策として、Freeは登録確認済みアカウントに限り、同一端末や同一IPからの複数登録を別途検知します。
- 管理者向けに、利用者別の消費トークンを上位から並べる画面を用意し、上限の見直し材料にします。
- 上限の数値は、運用開始後に実際の分布を見て再調整します。プラン規約への変更可能性の記載だけで済ませず、変更時の告知や既存契約への適用手順も決めます。
- 上流の上限や階層は変わるため、この記事の説明用の数値はそのまま使わず、契約中の画面で確認してください。
確認した範囲
本文で参照した上流の仕様は、2026年10月29日のGPTによる自動校閲で各社の公式ドキュメント本文と照合しました。上限値や階層、モデル名は変わりうるため、実装時に最新のページを見てください。比較表の方式の長短、設計シートの数値、照合式、コード例は編集上の提案と説明用の例であり、実測や検証の結果ではありません。

