レートリミットの扱い
公開APIにはテナント単位の呼び出し回数制限があります。超過時に返る 429 の見分け方、一過性のエラーだけを対象にした安全なリトライの組み方、SSGのビルド時に起きやすい大量アクセスの避け方をまとめます。
1. レート制限の考え方
公開APIの呼び出しは、テナント単位で毎分の上限が設けられています。上限を超えたリクエストは処理されず、429 が返ります。
- テナント単位:公開APIの読み取り系エンドポイントすべてに適用される、毎分の呼び出し回数上限です。
- 閲覧者単位:フォーム送信APIは、これに加えて同一送信元からの連続送信にも別枠の制限がかかります。
2. 429 と Retry-After
上限を超えると ShareDanCmsApiError がスローされ、isRateLimited
が true になります(status は 429、code は
E001003)。サーバー側で待機秒数を示せる場合は retryAfter
に秒数が入り、示せない場合は null です。
src/lib/cms-request.ts
import { ShareDanCmsApiError } from '@sharedan/cms-sdk';
try {
await cms.posts.list('news', { perPage: 100 });
} catch (err) {
if (err instanceof ShareDanCmsApiError && err.isRateLimited) {
console.log(err.status); // 429
console.log(err.code); // 'E001003'
console.log(err.retryAfter); // 待機秒数(例: 3)。示せない場合は null
}
throw err;
} 3. リトライ(指数バックオフ)
リトライしてよいのは、時間が経てば解消する一過性のエラー(429・5xx・ネットワーク断)だけです。401/404/422 のような恒久的な4xxはリクエスト内容そのものの問題なので、待っても結果は変わらず、即座に失敗させます。
retryAfter があればそれを優先し、なければ
base * 2 ** (attempt - 1) で間隔を広げます。
src/lib/with-retry.ts
import { ShareDanCmsApiError, ShareDanCmsNetworkError } from '@sharedan/cms-sdk';
async function withRetry<T>(fn: () => Promise<T>, maxAttempts = 4, base = 1000): Promise<T> {
for (let attempt = 1; ; attempt++) {
try {
return await fn();
} catch (err) {
const retryable =
err instanceof ShareDanCmsNetworkError ||
(err instanceof ShareDanCmsApiError && (err.isRateLimited || err.status >= 500));
if (!retryable || attempt >= maxAttempts) throw err;
const waitMs =
err instanceof ShareDanCmsApiError && err.retryAfter != null
? err.retryAfter * 1000
: base * 2 ** (attempt - 1);
await new Promise((resolve) => setTimeout(resolve, waitMs));
}
}
} 4. ビルド時の大量取得
SSGのビルドで「一覧を取得 → 各詳細ページをそれぞれ取得」のように大量のリクエストを一度に投げると、レート制限に達しやすくなります。全件を一斉に並列取得するのではなく、逐次、または小さめの並列数に抑え、同一ビルド内で同じリソースを二重に取得しないようメモ化しておくと安定します。
429 は一過性なので、指数バックオフで待てば解決します。一方
401(認証エラー)・404(存在しない)・422(バリデーションエラー)はリクエスト内容の問題であり、リトライしても解決しません。即座に失敗させ、ビルドログに残しましょう。
FEEDBACK
このページはお役に立ちましたか?
改善要望・不具合・ドキュメントの分かりにくい点など、お気軽にお寄せください。いただいた内容は今後の改善に役立てます。
フィードバックを送信しました
お寄せいただきありがとうございます。今後の改善に役立てます。