APIの呼び出し上限に合わせてワークフローを設計する

・ 朝倉 凛

少量の試行が通っても大量処理では崩れる理由

小さなデータセットで通った連携が、大量のレコードで途端に失敗することがある。 呼び出し回数が増えるほど、提供側は速度を落とすよう求めてくるからだ。 資料は、この制御を一定期間あたりのリクエスト数に上限を置く仕組みとして説明している。 上限は毎分や毎日で定義されたり、エンドポイントごとに個別の枠を持ったりする。

実装の形も一様ではない。 短時間のバーストを許す方式もあれば、一定レートで平準化する方式もある。 上限に達したときの標準応答は 429 Too Many Requests で、再試行までの待機時間を示す Retry-After ヘッダーが付く場合があると資料はしている。 自動化では、これを単なる失敗ではなく継続のための指示として扱う設計が要る。

各社ドキュメントが述べる上限の決め方と通知

上限を支える代表的なアルゴリズムとして、資料は4種を挙げる。 トークンバケットは蓄えたトークンの範囲でバーストを通し、時間とともに補充される。 リーキーバケットはキューに詰め、一定速度で処理してスパイクを平準化する。 固定ウィンドウは区切られた時間内の回数で数え、スライディングウィンドウは過去の一定期間を転がし窓で評価する。 アルゴリズム自体を知るより、提供側が残量やリセット時刻をどう伝えるかが重要だと資料は述べる。

具体例として、Stripe は上限を数値で示し、超過時は 429 を返すと記している。 本番のグローバル上限は毎秒100リクエスト、サンドボックスは毎秒25リクエストとしている。 個々のエンドポイントには毎秒25リクエストの枠があるとし、超過理由を示す Stripe-Rate-Limited-Reason ヘッダーを返すとしている。 さらに、同時実行制限をレート制限とは別枠で数えると資料は説明する。

AWS API Gateway はトークンバケットを使うと明記している。 アカウント単位かつリージョン単位でのレートとバーストを見て、超過時は 429 を返すとしている。 ステージやメソッドごとの目標値を設定できる一方、スロットルとクォータはベストエフォートであり、厳密な上限値というより目標として扱うべきだと資料は述べる。 429 を受け取ったクライアントは、レートを抑えて再送する実装が前提になる。

GitHub の資料は、エンドポイントごとに HTTP メソッドとパスが定義されることを説明している。 どの単位で数を数えるかはこの定義に依存するため、エンドポイント単位の上限を持つAPIでは仕様の読み違いが失敗の原因になる。

上限の定義の差が自動処理に生むリスク

固定ウィンドウを前提にした待機は、窓の境目で呼び出しが集中しやすい。 資料はスライディングウィンドウがこのスパイクを避ける狙いだとしている。 提供側の窓の切り方を把握せずに境界で一斉送信すると、直後に 429 が並んで遅延が連鎖する。 時間での分散やキューでの平準化が要る理由はここにある。

エンドポイント単位とグローバル単位が併存するAPIでは、どちらも満たす必要がある。 Stripe の資料は個別エンドポイントの上限に加えてグローバル上限があるとしている。 読みと書きの処理を別ワーカーで並列にすると、片方の枠は余っていてもグローバルの枠で頭打ちになることがある。 上限の単位を設計要素として露出し、投入速度をそれぞれに合わせて制御する必要がある。

同時実行制限はレートとは別に数えられると Stripe は説明する。 長時間のリクエストが溜まると、レートを下げても同時実行数が先に限界に達する。 この場合は並列数の上限やバッチサイズの見直しが効く。 短い多数のリクエストと、少数の長いリクエストでは、詰まり方の機構が違うため対処も変わる。

AWS API Gateway の資料は、設定は目標値であり厳密な天井ではないと述べる。 他要因で一時的に目標を上回ることがあり得るため、ぴったり目標に張り付く運用は 429 を誘発しやすい。 安全余裕を持たせる、もしくは通知ヘッダーに従って待機時間を調整する実装にしておくと、再試行の嵐を避けやすい。

設計の指針と実装時の留保

まず、提供側が出す情報を最優先に使う。 429 を受けたら Retry-After の秒数や、Stripe のような理由ヘッダーを読み取り、待機や再送のタイミングを決める。 ヘッダーが無いAPIでは、待機を挟んだ再送ポリシーを置くが、提供側のヘッダーに従う実装が基本である点は外さない。 失敗をログに残し、どの単位の上限に当たったかを後から追えるようにする。

次に、速度の制御をワークフローの外形として設ける。 キューで投入を並べ、ワーカー数で同時実行を縛ると、レートと同時実行を分離して調整できる。 資料は最適なアルゴリズムが一つに定まるわけではないとしているため、突発的な山を許したいならトークンバケット、平準化したいならリーキーバケットというように、期待するトラフィックに合わせて選ぶ。 固定・スライディングの窓を使う場合は、境界での偏りが出ないよう、投入のタイミングを分散させる。

さらに、バッチの粒度と周期を設計に含める。 1回に扱う件数を小さくし、リクエストの間隔を伸ばすと、同時実行とレートの双方に余裕が生まれる。 エンドポイント単位の上限があるAPIでは、処理をエンドポイントごとに分け、キューも別にするほうが安全に伸ばせる。 上限が日次のAPIでは、日付の境界直後に集中させず、複数の時間帯に散らして呼び出す。

最後に、仕様の読み替えや推測で実装を固めない。 Stripe は数値を明示し、AWS は目標として扱うと明言するなど、前提がサービスごとに異なる。 この差は再試行の強さや待機の設計に直結するため、一次資料の用語と単位をそのまま設計に写す。 上限は守れば必ず失敗しない保証ではないが、通知に従って速度を制御すれば、失敗しても回復が速い設計に近づける。

出典

  1. API Rate Limiting for More Reliable Workflows — n8n Blog (一次情報)
  2. Rate limiting — GitHub Docs (一次情報)
  3. Rate limits — Stripe (一次情報)
  4. Set up throttling for a REST API in API Gateway — Amazon Web Services (AWS) (一次情報)