ในบทความนี้ เราจะแสดงวิธี Rate Limit Next.js API Routes โดยใช้ Upstash Rate Limit SDK
การตั้งค่าฐานข้อมูล
สร้าง Redis Database ผ่าน Upstash Console หรือ Upstash CLI คัดลอก UPSTASH_REDIS_REST_URL และ UPSTASH_REDIS_REST_TOKEN ไปใช้ในขั้นตอนถัดไป
การตั้งค่าโปรเจกต์
เราจะสร้าง Next.js Application และ Deploy ไปที่ Vercel
npx create-next-app@latest
ติดตั้ง @upstash/ratelimit:
npm install @upstash/ratelimit @upstash/redis
โค้ด
อัปเดต pages/api/hello.js ดังด้านล่าง และแทนที่ UPSTASH_REDIS_REST_URL และ UPSTASH_REDIS_REST_TOKEN
// pages/api/hello.js
import {Ratelimit} from "@upstash/ratelimit";
import {Redis} from "@upstash/redis";
const redis = new Redis({
url: 'UPSTASH_REDIS_REST_URL',
token: 'UPSTASH_REDIS_REST_TOKEN',
});
// สร้าง Rate Limiter ใหม่ อนุญาต 5 Requests ต่อ 5 วินาที
const ratelimit = new Ratelimit({
redis: redis,
limiter: Ratelimit.fixedWindow(5, "5 s"),
});
export default async function handler(req, res) {
// ใช้ String คงที่เพื่อจำกัดทุก Request ด้วย Rate Limit เดียว
// หรือใช้ UserID, API Key หรือ IP Address สำหรับ Limit แบบรายบุคคล
const identifier = "api";
const result = await ratelimit.limit(identifier);
res.setHeader('X-RateLimit-Limit', result.limit);
res.setHeader('X-RateLimit-Remaining', result.remaining);
if (!result.success) {
res.status(200).json({message: 'The request has been rate limited.', rateLimitState: result});
return;
}
res.status(200).json({name: 'John Doe', rateLimitState: result});
}
ที่นี่ เราอนุญาต 5 Requests ต่อ 5 วินาที
รัน
รันแอปด้วย npm run dev รีเฟรชเบราว์เซอร์มากกว่า 5 ครั้ง และคุณจะเห็น Rate Limiting ทำงาน
{"message":"The request has been rate limited.","rateLimitState":{"success":false,"limit":5,"remaining":-1,"reset":1654546770000,"pending":{}}}
การปรับปรุงที่เป็นไปได้
- ใช้ User ID หรือ IP Address ของผู้ใช้เป็น Identifier เพื่อจำกัดการใช้งานต่อคน
const identifier = getClientIp(req);
const result = await ratelimit.limit(identifier);
- ใช้ Sliding Window Algorithm สำหรับ Rate Limiting ที่เรียบเนียนกว่า (แต่ค่าใช้จ่ายสูงกว่า)
const ratelimit = new Ratelimit({
redis: redis,
limiter: Ratelimit.slidingWindow(10, "10 s"),
});
- ใช้ Token Bucket Algorithm เพื่อรองรับ Spike บางส่วน
const ratelimit = new Ratelimit({
redis: redis,
limiter: Ratelimit.tokenBucket(5, "10 s", 10),
});
ใช้ Multiple Redis ใน Region ต่างๆ หาก Next.js Application ของคุณ Deploy ไปหลาย Region จะช่วยลด Latency สำหรับตำแหน่งต่างๆ
เก็บและอ่าน Upstash Redis Credentials จาก Environment Variables หรือ Secret Store