GitHubは、アプリが送信できる REST API 要求の数を制限します。 制限を超えると、GitHubは、制限がリセットされるか待機時間が経過するまで、403または429ステータスでリクエストを拒否します。 GitHubには 2 種類の制限があります。1 時間あたりの要求に対する主な制限と、急増を防ぐセカンダリ制限です。 レート制限されている間もアプリがリクエストを送信し続けると、GitHub があなたのインテグレーションを禁止する可能性があります。 詳細については、「REST API のレート制限」を参照してください。
GitHubのレート制限とは
| Limit | Value | それを確認するとき |
|---|---|---|
| 主, 認証されていない | 1 時間あたり、IP アドレスあたり 60 件の要求 |
403 または 429、 x-ratelimit-remaining が 0 |
| メイン、個人用アクセス トークン | 1 時間あたり 5,000 件の要求 | 同上 |
GitHub Actions の GITHUB_TOKEN プライマリ |
1 リポジトリあたり 1 時間ごとに 1,000 リクエスト | 同上 |
| Secondary | たとえば、同時要求数は 100 個以下、REST エンドポイントの場合は 1 分あたり 900 ポイント、コンテンツ生成要求数は 1 分あたり約 80 個です。 |
403 またはエラー メッセージ付きの 429。
retry-after が存在する可能性があります。 |
GitHubは、予告なしにセカンダリの制限を変更できます。また、その制限にどの程度近づいているかを確認する方法はありません。
すべての応答には、プライマリ制限の現在の使用状況を示すヘッダーが含まれています。
| Header | それがあなたに伝えるもの |
|---|---|
x-ratelimit-limit |
1 時間あたりに送信できるリクエストの最大数 |
x-ratelimit-remaining |
現在のウィンドウで残っているリクエスト数 |
x-ratelimit-used |
現在のウィンドウで送信した要求の数 |
x-ratelimit-reset |
ウィンドウがリセットされるとき(UTC エポック秒) |
x-ratelimit-resource |
リクエストがどの制限に対してカウントされるか |
GitHub のレート制限に対処する方法
- レート制限とアクセス許可エラーを見分けます。 GitHubは、トークンに必要なアクセス権限がない場合にも
403を返します。 応答にretry-afterがなく、x-ratelimit-remainingが0されておらず、メッセージにレート制限が記載されていない場合は、アクセス許可の問題です。 再試行しないでください。 - 最初に
retry-afterを選択してください。 ヘッダーが存在する場合は、その秒数待ちます。 - それ以外の場合は、リセットを待ちます。
x-ratelimit-remainingが0の場合は、x-ratelimit-resetの時刻まで再試行しないでください。 - そうでない場合は、1分以上待ってください。 どちらのヘッダーもないセカンダリ制限の場合、GitHub は少なくとも 1 分間待機し、再試行が失敗するたびにさらに長く待つよう求めます。 設定した回数の再試行後に停止し、エラーを発生させます。
-
上限に達する前にペースを落としてください。
x-ratelimit-remainingとx-ratelimit-resetを使用して、要求のペースを設定します。 GitHubによって制限が変更される可能性があるため、正確な残りの数に関するロジックを構築しないでください。x-ratelimit-*ヘッダーは、GET /rate_limitエンドポイントではなく、信頼できる情報源です。
async function githubWaitMs(response, attempt) {
if (response.status !== 403 && response.status !== 429) {
return null;
}
const retryAfter = response.headers.get('retry-after');
if (retryAfter) {
return Number(retryAfter) * 1000;
}
if (response.headers.get('x-ratelimit-remaining') === '0') {
const resetMs = Number(response.headers.get('x-ratelimit-reset')) * 1000;
return Math.max(resetMs - Date.now(), 0);
}
const { message = '' } = await response.clone().json().catch(() => ({}));
if (response.status === 429 || /rate limit/i.test(message)) {
return 60_000 * 2 ** attempt;
}
// A 403 without rate limit signals is a permission problem: don't retry
return null;
}
呼び出し元は、関数が数値を返したときに再試行し、数回試行した後に停止します。
アプリがGitHubレート制限を処理することをテストする方法
開発中にGitHubレート制限に達することはめったにありません。 いくつかの要求を送信すると、1時間あたり5,000件が無限にあるように感じられます。 そのため、レート制限の処理をテストする方法によって、ユーザーが見つける前にバグが見つかるかどうかを決めます。
| Approach | 見つけたもの | 見逃したもの |
|---|---|---|
| 本番環境を待つ | 実際の失敗 | ユーザーがそれを押すまでのすべて |
| テストで API をモックするか、コーディング エージェントにモックを記述させる | 再試行ブランチを実行するかどうか | GitHubの実際のヘッダーとエラー本文、および SDK の再試行ポリシー。 アプリでは、モックに到達するためにテスト専用のスイッチも必要です。 |
| 制限されるまで実際のAPIを呼び出してください | 実際の動作 | 最大 5,000 件のリクエストがかかります。必要に応じて 2 次的な制限をトリガーすることはできません。統合が禁止されるおそれがあります |
| アプリの実際のトラフィックをインターセプトし、要求に応じてレート制限の応答を返します | 実際の URL、実際の SDK と再試行ポリシー、GitHub独自のヘッダーとエラー形式 | アプリ内では何も変更されないため、コードを独立した状態でテストするわけではありません。 そのための単体テストは残しておいてください。 |
アプリで試す
Dev Proxyは、アプリのapi.github.comへの要求をインターセプトし、GitHubスタイルのレート制限応答を返しますが、アプリは実際のURLを呼び出し続けます。
github-rate-limitingプリセットでは、リクエストは 1 時間あたり 60 回の上限としてカウントされ、x-ratelimit-* ヘッダーを送信し、上限に達すると 429 を含む API rate limit exceeded を返します。それまでは、リクエストは GitHub に送られ、実際の上限に対してもカウントされます。
プリセットをダウンロードし、それを使用して開発プロキシを起動します。
devproxy config get github-rate-limiting
devproxy --config-file "~dataFolder/configs/github-rate-limiting/.devproxy/devproxyrc.json"
セカンダリの制限をテストするには、代わりに同じフォルダーから devproxyrc-secondary.json を使用して Dev Proxy を起動します。 セカンダリ レート制限retry-after を 429 ヘッダーを伴ってランダムに返します。
その後、通常どおりにアプリを実行し、アプリがどのように動作するかを確認します。 開発プロキシをインストールするには、「 開発プロキシの設定」を参照してください。
次のステップ
参照
Dev Proxy