Cách giới hạn Rate Limit cho API AI trong Next.js để bảo vệ ngân sách
Các cuộc gọi API AI (như OpenAI hoặc Anthropic) có chi phí rất cao, và một lỗi nhỏ hoặc hành vi của người dùng có thể làm tăng hóa đơn nhanh chóng. Bài viết này sẽ hướng dẫn bạn triển khai cơ chế giới hạn tốc độ (rate limit) nhiều lớp cho các tuyến đường AI trong Next.js, giúp kiểm soát chi phí theo từng người dùng và gói dịch vụ.

Các cuộc gọi API AI ngày nay cực kỳ đắt đỏ. Chỉ cần một người dùng chạy script tự động, một lỗi nhỏ ở frontend, hoặc một kẻ tấn công độc hại là hóa đơn hàng tháng của bạn có thể "cháy túi" trước khi bạn kịp nhận ra.
Dưới đây là hướng dẫn chi tiết cách thêm cơ chế giới hạn tốc độ (rate limit) theo từng người dùng cho các tuyến đường (route) AI, đảm bảo không ai có thể làm cạn kiệt ngân sách Anthropic hay OpenAI của bạn.
Tại sao các tuyến đường AI cần giới hạn đặc biệt?
Khác với các API thông thường, chi phí tính toán của AI mô hình lớn (LLM) là rất lớn. Hãy xem so sánh ước tính sau:
- Chi phí gọi API thông thường: ~0,001 cent.
- Cuộc gọi Claude Sonnet (1k tokens vào, 1k tokens ra): ~0,3 cent.
- Cuộc gọi GPT-4o (1k tokens vào, 1k tokens ra): ~0,5 cent.
Con số này nghe có vẻ nhỏ, nhưng hãy nhìn vào tổng cộng:
-
Với 1.000 yêu cầu từ một người dùng:
- API thông thường: 0,01$ (không đáng kể).
- Claude Sonnet: 3,00$ (đã bắt đầu đáng chú ý).
- GPT-4o: 5,00$.
-
Với 10.000 yêu cầu (do script bị lỗi hoặc kẻ tấn công):
- Claude Sonnet: 30$ chỉ trong vài phút.
- GPT-4o: 50$ chỉ trong vài phút.
Rõ ràng, nếu không có lớp bảo vệ, rủi ro tài chính là rất lớn.
Cách tiếp cận hai lớp (Two-Layer Approach)
Để bảo vệ tối ưu, chúng ta sẽ sử dụng kết hợp hai lớp giới hạn:
- Lớp 1 (Burst Limit): Giới hạn trong thời gian ngắn để ngăn chặn việc spam yêu cầu liên tục.
- Lớp 2 (Daily Budget Limit): Giới hạn tổng số yêu cầu trong ngày để ngăn chặn việc khai thác tài nguyên kéo dài.
Dưới đây là đoạn mã mẫu lib/ai-rate-limit.ts sử dụng TypeScript:
// lib/ai-rate-limit.ts
// Layer 1: Short burst limit (ngăn chặn lạm dụng tức thời)
// Layer 2: Daily budget limit (ngăn chặn rút cạn tài nguyên dài hạn)
import { rateLimit } from './rate-limit'
export async function checkAIRateLimit(userId: string) {
// 10 requests per minute (burst)
const burst = rateLimit({
key: `ai:burst:${userId}`,
limit: 10,
windowMs: 60_000 // 1 phút
})
if (!burst.success) {
return {
allowed: false,
error: 'Quá nhiều yêu cầu. Vui lòng đợi một phút trước khi thử lại.',
retryAfter: 60
}
}
// 100 requests per day (budget)
const daily = rateLimit({
key: `ai:daily:${userId}`,
limit: 100,
windowMs: 24 * 60 * 60_000 // 24 giờ
})
if (!daily.success) {
return {
allowed: false,
error: 'Đạt giới hạn yêu cầu AI trong ngày. Giới hạn sẽ được đặt lại vào nửa đêm.',
retryAfter: 86400
}
}
return { allowed: true, remaining: daily.remaining }
}
Giới hạn dựa trên gói dịch vụ (Plan-Based Limits)
Thông thường, các ứng dụng SaaS sẽ có các gói khác nhau như Free, Pro và Enterprise. Bạn nên áp dụng các giới hạn khác nhau cho từng gói:
const AI_LIMITS = {
free: { burst: 5, daily: 20 },
pro: { burst: 30, daily: 500 },
enterprise: { burst: 100, daily: 10_000 },
} as const
export async function checkPlanAILimit(
userId: string,
plan: keyof typeof AI_LIMITS
) {
const limits = AI_LIMITS[plan]
const burst = rateLimit({
key: `ai:burst:${userId}`,
limit: limits.burst,
windowMs: 60_000
})
if (!burst.success) {
return {
allowed: false,
error: `Giới hạn tốc độ: ${limits.burst} yêu cầu/phút với gói ${plan}`
}
}
const daily = rateLimit({
key: `ai:daily:${userId}`,
limit: limits.daily,
windowMs: 24 * 60 * 60_000
})
if (!daily.success) {
return {
allowed: false,
error: `Giới hạn ngày: ${limits.daily} lượt gọi AI/ngày với gói ${plan}. Hãy nâng cấp để dùng thêm.`
}
}
return { allowed: true, remaining: daily.remaining }
}
Tích hợp vào AI Route trong Next.js
Bước cuối cùng là đưa logic kiểm tra này vào trong API Route của bạn (ví dụ: app/api/generate/route.ts).
// app/api/generate/route.ts
import { NextRequest, NextResponse } from 'next/server'
import { getServerSession } from 'next-auth'
import { authOptions } from '@/lib/auth'
import { checkPlanAILimit } from '@/lib/ai-rate-limit'
import { db } from '@/lib/db'
import Anthropic from '@anthropic-ai/sdk'
const anthropic = new Anthropic()
export async function POST(req: NextRequest) {
const session = await getServerSession(authOptions)
if (!session) return NextResponse.json({ error: 'Chưa xác thực' }, { status: 401 })
// Lấy gói dịch vụ của người dùng
const user = await db.user.findUnique({
where: { id: session.user.id },
include: { subscription: true }
})
const plan = (user?.subscription?.plan ?? 'free') as 'free' | 'pro' | 'enterprise'
// Kiểm tra rate limit
const check = await checkPlanAILimit(session.user.id, plan)
if (!check.allowed) {
return NextResponse.json(
{ error: check.error },
{ status: 429 } // 429 Too Many Requests
)
}
const { prompt } = await req.json()
// Gọi API AI
const message = await anthropic.messages.create({
model: 'claude-sonnet-4-6',
max_tokens: 1024,
messages: [{ role: 'user', content: prompt }]
})
return NextResponse.json({
result: message.content[0].type === 'text' ? message.content[0].text : '',
remaining: check.remaining
})
}
Theo dõi dựa trên Token (Nâng cao)
Ví dụ trên đếm số lượng request. Tuy nhiên, để quản lý ngân sách chặt chẽ hơn, bạn nên theo dõi số lượng token thực tế đã sử dụng và chi phí tương ứng.
// Theo dõi chi tiêu token thực tế, không chỉ đếm request
const message = await anthropic.messages.create({ ... })
// Ghi nhật ký sử dụng
await db.aiUsage.create({
data: {
userId: session.user.id,
inputTokens: message.usage.input_tokens,
outputTokens: message.usage.output_tokens,
model: 'claude-sonnet-4-6',
costCents: Math.ceil(
(message.usage.input_tokens * 0.003 + message.usage.output_tokens * 0.015) / 10
) // Ước tính, hãy cập nhật theo giá hiện tại
}
})
// Kiểm tra giới hạn chi tiêu hàng tháng
const monthlySpend = await db.aiUsage.aggregate({
where: {
userId: session.user.id,
createdAt: { gte: startOfMonth }
},
_sum: { costCents: true }
})
if ((monthlySpend._sum.costCents ?? 0) > USER_MONTHLY_LIMIT_CENTS) {
return NextResponse.json({ error: 'Đã vượt quá ngân sách AI hàng tháng' }, { status: 429 })
}
Việc triển khai rate limiting không chỉ giúp bảo vệ ví tiền của bạn mà còn đảm bảo hệ thống ổn định cho tất cả người dùng.
Bài viết liên quan

Phần mềm
Ra mắt Rail: Ngôn ngữ lập trình tự hosting tích hợp HTTPS thuần túy
18 tháng 4, 2026

Phần mềm
Tương lai "Headless" cho AI cá nhân: Khi giao diện dòng lệnh lên ngôi
18 tháng 4, 2026

Công nghệ
Cursor đàm phán huy động hơn 2 tỷ USD với định giá 50 tỷ USD khi tăng trưởng doanh nghiệp bùng nổ
17 tháng 4, 2026
