【ITニュース解説】Fixed Window Rate Limiting: Concept, Examples, and Java Implementation

2025年09月09日に「Dev.to」が公開したITニュース「Fixed Window Rate Limiting: Concept, Examples, and Java Implementation」について初心者にもわかりやすいように丁寧に解説しています。

作成日: 更新日:

ITニュース概要

Webサービスへのアクセスを制御する固定ウィンドウレートリミットは、時間を区切ってリクエスト数を制限する手法だ。実装が簡単な点が長所だが、区間の境目でアクセスが集中する短所も。単一マシンやRedisを使った分散環境での実装がある。(118文字)

ITニュース解説

WebサービスやAPIを開発・運用する上で、サービスの安定性を保ち、不正な利用を防ぐことは非常に重要である。そのための基本的な技術の一つが「レートリミット」と呼ばれる仕組みである。これは、特定の時間内に特定のユーザーやIPアドレスから受け付けるリクエストの数を制限する機能であり、特定のユーザーによる過剰なアクセスでサーバーに負荷がかかりすぎるのを防いだり、パスワードを何度も試すような攻撃を緩和したりできる。このレートリミットを実現するアルゴリズムはいくつか存在するが、今回はその中でも最もシンプルで理解しやすい「固定ウィンドウ(Fixed Window)」方式について解説する。

固定ウィンドウ方式は、その名の通り、時間を固定長の区間、つまり「ウィンドウ」に区切ってリクエスト数を管理するアルゴリズムである。考え方は非常に単純で、まず「1分間」や「1時間」といった時間のウィンドウを定義する。そして、そのウィンドウごとに許可するリクエストの最大数を設定する。リクエストが来るたびに、現在のウィンドウ内でのリクエスト数を数え、上限に達していなければリクエストを受け付け、カウンターを1つ増やす。もしカウンターが上限に達していれば、そのリクエストは拒否される。そして、時間が経過して次のウィンドウに移ると、カウンターはゼロにリセットされ、再び上限までリクエストを受け付けられるようになる。具体例として、ログインAPIで「1ユーザーにつき1分間に10回まで」という制限を考えてみる。あるユーザーが午前10時00分から10時00分59秒までの1分間に10回ログインを試行した場合、11回目のリクエストは拒否される。しかし、時刻が午前10時01分00秒になった瞬間、新しい1分間のウィンドウが始まるため、カウンターはリセットされ、このユーザーは再び10回までログインを試行できるようになる。

この方式の最大のメリットは、そのシンプルさにある。仕組みが直感的で理解しやすく、プログラムとして実装するのも比較的簡単である。また、管理する情報もユーザーごとのカウンターとウィンドウの開始時刻くらいであるため、サーバーのメモリや計算資源への負荷が少ないという利点もある。一方で、このシンプルさゆえの弱点も存在する。最も大きな問題は、ウィンドウの境界でリクエストが集中する「バースト」を許してしまうことである。先の例で言えば、あるユーザーが午前10時00分59秒に10回のリクエストを送り、直後の午前10時01分00秒にさらに10回のリクエストを送ることが可能である。この場合、実質的には2秒ほどの間に20回のリクエストが集中することになり、これは本来制限したかった意図とは異なる結果を生む可能性がある。このようなリクエストの集中は、サーバーに瞬間的な高い負荷をかける原因となり得る。

固定ウィンドウレートリミットを実装する方法は、システムの規模によって大きく二つに分けられる。一つは、サーバーが1台、もしくは小規模な構成で稼働しているシステム向けの「単一マシンでの実装」である。この場合、サーバーのメモリ上に、ユーザーIDと、そのユーザーのリクエスト回数および現在のウィンドウの開始時刻を記録するデータ構造を用意する。リクエストが来るたびにこの情報を参照・更新することで、レートリミットを実現する。複数のリクエストが同時に処理されることを考慮し、カウンターの更新が競合しないように排他制御を正しく行う必要があるが、外部のシステムに依存しないため、手軽に導入できる。もう一つは、複数のサーバーで構成される大規模な分散システム向けの「分散実装」である。この場合、各サーバーが個別にカウンターを持つと、ユーザーからのリクエストが異なるサーバーに振り分けられた際に、全体の制限を正しく適用できない。これを防ぐために、全てのサーバーから参照できる中央集権的なカウンターが必要となる。この共有カウンターとして、Redisのような高速なインメモリデータストアがよく利用される。Redisを使えば、あるユーザーからのリクエスト数をアトミックに(処理の途中で割り込まれることなく安全に)増やす操作や、キーに有効期限(ウィンドウの期間)を設定する操作が簡単に行えるため、分散環境でも一貫性のあるレートリミットを効率的に実現できる。

Redisのような外部システムを共有カウンターとして利用する場合、その外部システムが停止した際の挙動、つまり耐障害性を考慮する必要がある。もしRedisが利用できなくなった場合、レートリミットのチェックができなくなる。このとき、安全側に倒して全てのリクエストを拒否するのか、それとも一時的に制限を解除して全てのリクエストを受け付ける(フェイルオープン)のか、といったポリシーをあらかじめ決めておく必要がある。一般的には、レートリミット機能が停止してもサービスの根幹機能は提供し続けるために、フェイルオープンを選択することが多い。

固定ウィンドウレートリミットは、実装の容易さと低コストから、多くの場面で採用される基本的なアルゴリズムである。特に、厳密なリクエスト間隔の制御が不要で、ある程度のバーストを許容できるユースケースには非常に適している。しかし、ウィンドウ境界でのリクエスト集中という弱点も存在するため、システムの要件をよく理解した上で採用を検討する必要がある。また、システムの規模に応じて、単一マシンでの実装と、Redisなどを用いた分散実装を適切に選択し、特に後者の場合は耐障害性まで考慮することが、安定したサービス運用には不可欠である。

【ITニュース解説】Fixed Window Rate Limiting: Concept, Examples, and Java Implementation | いっしー@Webエンジニア