レート制限
API は、(キーごとではなく)チームごとの 1 秒あたりのリクエスト数を制限します。
| プラン | 1 秒あたりのリクエスト数 |
|---|---|
| Free | 10 |
| Pro | 10 |
| Scale | 25 |
| Enterprise | 個別設定 |
Resend の上限は 1 秒に 2 リクエストです。最大 100 通のバッチは1 つのリクエストなので、上限の範囲内で 1 秒あたり数千通を送信できます。
制限は 1 秒のウィンドウで適用されます。ダッシュボードのセッションにはレート制限がありません。送信のクォータ(プランとクォータ)は、リクエストの制限とは別です。
すべてのレスポンスに、次のヘッダーが含まれます。
| ヘッダー | 意味 |
|---|---|
ratelimit-limit |
ウィンドウあたりに許可されるリクエスト数(たとえば 10)。 |
ratelimit-remaining |
現在のウィンドウで残っているリクエスト数。 |
ratelimit-reset |
ウィンドウがリセットされるまでの秒数(1)。 |
retry-after |
429 のときのみ: 再試行するまでに待つ秒数(1)。 |
HTTP/1.1 429 Too Many Requestsratelimit-limit: 10ratelimit-remaining: 0ratelimit-reset: 1retry-after: 1
{ "statusCode": 429, "name": "rate_limit_exceeded", "message": "Too many requests. You can only make 10 requests per second." }429 の処理
Section titled “429 の処理”import { SpacePost, type SendEmailOptions } from "@spacepost/node";
const spacepost = new SpacePost();
async function sendWithRetry(email: SendEmailOptions, key: string, attempts = 5) { for (let i = 0; i < attempts; i++) { const { data, error } = await spacepost.emails.send(email, { idempotencyKey: key }); if (!error) return data; if (error.name !== "rate_limit_exceeded") throw new Error(`${error.name}: ${error.message}`); await new Promise((r) => setTimeout(r, 1000 * (i + 1))); } throw new Error("rate limited");}import time, requests
def post_with_retry(url, headers, json, attempts=5): for _ in range(attempts): r = requests.post(url, headers=headers, json=json, timeout=15) if r.status_code != 429: return r time.sleep(float(r.headers.get("retry-after", 1))) return r実際には成功していたリクエストが重複しないよう、再試行では必ず同じ Idempotency-Key を再利用してください。
- 個別の送信を多数行うより、バッチを使いましょう。
- 送信はバックグラウンドのワーカーでキューに入れ、同時実行数を上限に合わせて制限します。
- インポート処理(たとえばコンタクトの作成)は、一定のペースに分散させましょう。