Prevent abuse, DDoS attacks, and excessive API usage.
- MVP: Optional (focus on features first)
- Production with users: Recommended on auth endpoints and public APIs
- Public-facing APIs: Required
npm install @upstash/ratelimit @upstash/redis- Go to upstash.com (free tier: 10k requests/day)
- Create a Redis database
- Copy REST URL and token
# .env.local
UPSTASH_REDIS_REST_URL=https://xxx.upstash.io
UPSTASH_REDIS_REST_TOKEN=xxx// src/lib/rate-limit.ts
import { Ratelimit } from '@upstash/ratelimit'
import { Redis } from '@upstash/redis'
export const ratelimit = new Ratelimit({
redis: Redis.fromEnv(),
limiter: Ratelimit.slidingWindow(10, '10 s'), // 10 requests per 10 seconds
})// src/app/api/example/route.ts
import { ratelimit } from '@/lib/rate-limit'
import { NextRequest, NextResponse } from 'next/server'
export async function POST(request: NextRequest) {
const ip = request.headers.get('x-forwarded-for') ?? 'anonymous'
const { success, limit, remaining } = await ratelimit.limit(ip)
if (!success) {
return NextResponse.json(
{ error: 'Too many requests' },
{
status: 429,
headers: {
'X-RateLimit-Limit': limit.toString(),
'X-RateLimit-Remaining': remaining.toString(),
},
}
)
}
// Process request normally...
}// middleware.ts
import { ratelimit } from '@/lib/rate-limit'
import { NextRequest, NextResponse } from 'next/server'
export async function middleware(request: NextRequest) {
// Only rate limit API routes
if (request.nextUrl.pathname.startsWith('/api/')) {
const ip = request.headers.get('x-forwarded-for') ?? 'anonymous'
const { success } = await ratelimit.limit(ip)
if (!success) {
return NextResponse.json({ error: 'Too Many Requests' }, { status: 429 })
}
}
}
export const config = {
matcher: '/api/:path*',
}| Endpoint Type | Limit | Window |
|---|---|---|
| Login/Register | 5 requests | 1 minute |
| Password Reset | 3 requests | 5 minutes |
| General API | 30 requests | 10 seconds |
| File Upload | 5 requests | 1 minute |
Vercel Edge Config - Simpler but less flexible. Built into Vercel, no external service needed.