レート制限 は何をしますか?
ルール
- APIエンドポイントにはトークンバケット、認証/ログインルートにはスライディングウィンドウを使用する
- 呼び出し元はAPIキーで特定し、フォールバックとしてIPを使用する — 認証ルートではIPのみに依存しない
429 Too Many Requests と Retry-After ヘッダー(秒)、X-RateLimit-Remaining ヘッダーを返す
- カウンターはRedis(またはサーバーレス向けUpstash)に保存 — マルチインスタンスデプロイメントではインメモリに保存しない
- 賢いデフォルト値を設定: 一般APIは100 req/min、認証は5 req/min、読み取りは1000 req/min
- サーバーレスには
@upstash/ratelimit を使用 — Redisのアトミック性とスライディングウィンドウをネイティブに処理する
- レート制限はミドルウェアとして実装 — グローバルに適用し、ルートごとに厳しい制限でオーバーライドする
- Next.jsの場合: middleware.ts またはAPIルートハンドラでレート制限を行い、Reactコンポーネント内では行わない
- ティア(無料、プロ、エンタープライズ)ごとに制限を分ける — ティアはJWTまたはデータベースルックアップに保存する
- レート制限ヒットを呼び出し元のIDとともにログに記録 — 不正使用パターンを早期に検出する
パターン
import { Ratelimit } from "@upstash/ratelimit";
import { Redis } from "@upstash/redis";
const ratelimit = new Ratelimit({
redis: Redis.fromEnv(),
limiter: Ratelimit.slidingWindow(10, "10 s"),
analytics: true,
});
const { success, limit, remaining, reset } = await ratelimit.limit(identifier);
避けるべきこと
- サーバーレスまたはマルチインスタンス設定でのインメモリレート制限 — 呼び出し間で状態が失われる
- アプリケーション層のみでのレート制限 — CDN/エッジの制限(Cloudflare、Vercel)も追加する
- 過度に厳しい制限で正規ユーザーをブロックする — 緩やかに開始し、データに基づいて厳しくする
- Webhookや公開フォームへのレート制限を忘れる