36
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

posted at

updated at

Organization

WebAPIを設計するうえでの利用制限(Rate Limit)について調べた

経緯

APIを設計する時に「利用制限をどうすべきか」という議論が起きると思います。
とりあえず有名なAPIを調べて、傾向やビッグウェーブなどあればと思い調べました。

以下、各サービスのAPIドキュメントは2018年7月時点くらいに調べたものとなります。

結論(まとめ)

十人十色でした!!
言い換えると、共通のベストプラクティスという物は無さそうで
以下の2つの軸を元にサービスに応じてカスタマイズしていく形かなと考えます。

  1. 制限をかける粒度を選択 / 組み合わせる
    ・サービス(大きな機能)単位で制限
    ・機能に応じて何種類かの区分を作り制限
    ・APIエンドポイント単位で制限
    ・重要度に分けて制限
    ・認証の種類で制限

  2. 実行制限の枠(rate limit window)を決める
    制限を掛ける=リセットされるまでの、時間。

また、上記以外にもセットで現在の利用制限状況の表現方法を決める必要がありそうです。
特にリセットされるまでの表現について、後述で紹介するブログにも、非常に参考になる以下の記事にも記載がありますが、残り秒数にすべきという話があります。
参考:翻訳: WebAPI 設計のベストプラクティス

調べたAPIと結果

API制限といえばTwitterが有名かと思いますが、その他よく「イケてる」と耳にするAPIや、思いついたものを調べてみました。

  • GitHub
  • Google APIs
  • kintone
  • Twitter
  • Slack
  • Stripe

GitHub

制限時のHTTPステータス 参考URL
403 Forbidden API Document

制限の一例

  • search以外は1時間あたり5000req
  • searchのみ1分30req(認証なしの場合は1分10req)

特徴

  • searchとそれ以外でざっくりと定義されている。
  • ただし、不正利用検知のようなロジックがあり、条件を満たすと同様に403を返すようになる(詳細のメッセージにその旨記載される)
  • HTTPレスポンスヘッダに制限状況が記載される。

Google APIs

制限時のHTTPステータス 参考URL
403 FORBIDDEN API Document
※リンク先はYoutube Data API

制限の一例

  • ※クォータという概念で管理される。

特徴

  • 読み取りや書き取りなどリクエストによって消費されるクォータが異なる。
  • APIの種類ごとにクォータが設定されており、console より、[割り当て]から確認可能。

kintone

制限時のHTTPステータス 参考URL
記載なし(200以外) API Document

制限の一例

  • APIによる同時接続数はドメインごとに100が上限。

特徴

  • X-ConcurrencyLimit-Limitとして同時接続数の上限値を返却
  • X-ConcurrencyLimit-Runningとして現在の同時接続数を返却

Twitter

制限時のHTTPステータス 参考URL
429 Too Many Requests API Document1
API Document2
ヘルプセンター

制限の一例

  • 1日2400ツイート(※別途サービスに対しての制限もあり)。
    users/suggestions:15分あたり15回

特徴

  • 認証方法(ユーザー or アプリケーション)によってAPIエンドポイント単位で異なる制限が可能。
  • 投稿などはユーザー単位のみの制限が適用される。
  • HTTPレスポンスヘッダに当該APIの制限状況が記載される。
  • プレミアムプランだと制限は別(無し?)というマネタイズもあり。

Slack

制限時のHTTPステータス 参考URL
429 Too Many Requests API Document

制限の一例

  • メッセージの投稿は1秒1回など
  • 他、Web API methodsは1分あたり1~100回

特徴

  • 制限の種類を5つのTierに分類し、APIごとにそのTierが指定されている。
  • Retry-Afterヘッダで「再試行可能までの秒数」を返す

Stripe

制限時のHTTPステータス 参考URL
429 - Too Many Requests ブログ
API Document

制限の一例

  • ※具体的な閾値は言及なし

特徴

  • 4種類の制限方法を組み合わせている。
    • Request rate limiter(毎秒Nリクエストの制限)
    • Concurrent requests limiter(同時実行の制御)
    • Fleet usage load shedder(クリティカルなAPIの一定利用枠の確保)
    • Worker utilization load shedder(重要度の低い順からリクエストを切っていく)

上限到達エラー時のHTTPステータスコード

Twitter,Stripe,Slackが「429 Too Many Requests」を返し、
GitHub, Google APIsは「403 Forbidden」を返すのが特徴的です。
429はRFC6585に記載のあるやつですね。

現在の利用制限状況の表現方法

Twitter,GitHub, kintoneは独自のHTTPヘッダにて返します。
一方、今回調べた中ではSlackがrfc6585にも記載のあるRetry-Afterを用いています。

このあたりは2013年に言及された記事も見つけました。
HTTPヘッダにUNIX Timestampを入れるべきではないのか

なお独自のHTTPヘッダは、各サービスごとに名称と意味合いが若干異なっておりました。

Twitter

HTTPヘッダ名 説明
x-rate-limit-limit そのエンドポイントの上限
x-rate-limit-remaining ウィンドウ(15分)での残り要求可能数
x-rate-limit-reset (※残り時間っぽい表現ですが、UNIX timeなのでリセット時刻では)

GitHub

HTTPヘッダ名 説明
X-RateLimit-Limit 1時間あたりに許可されるリクエストの最大数。
X-RateLimit-Remaining ウィンドウでの残り要求可能数
X-RateLimit-Reset ウィンドウでの制限がリセットされる時刻。

kintone

HTTPヘッダ名 説明
X-ConcurrencyLimit-Limit 同時接続数の上限値
X-ConcurrencyLimit-Running 現在の同時接続数

所感

個人的にはGitHubの「サービス単位でシンプルな制限を課しつつ、別途不正利用検知という層を入れる」のが面白いなと思いました。
また、今回、そんなに沢山のサービスを調べた訳では無いですが、「ほぼ被っている」APIが1つも無かったことに驚きました。

RFCがーは理解しつつも、実際問題「あと1週間使えません」という時にClientに604800を返すのは険しいのではとも思ったのですが、そうした使い方は不正利用へのペナルティが目的となるはずで、今回のような話とは別に考えることなのだろうと思いました。
パフォーマンス維持を目的とするならRetry-Afterで足りるよう設計できるよね、と言われるとそうだなと思います。

Register as a new user and use Qiita more conveniently

  1. You can follow users and tags
  2. you can stock useful information
  3. You can make editorial suggestions for articles
What you can do with signing up
36
Help us understand the problem. What are the problem?