Loading...
Loading...
> Protect your API endpoints from abuse with configurable rate limiting middleware.
Rate limiting prevents abuse by limiting how many requests a user or IP can make in a given time period. This protects against DDoS attacks, brute force attempts, and API abuse.
DESC: Configure Upstash Redis for production rate limiting
1$# .env.local23$# Upstash Redis (get from https://upstash.com)4$UPSTASH_REDIS_REST_URL="https://your-redis.upstash.io"5$UPSTASH_REDIS_REST_TOKEN="your-redis-token"
Add rate limiting to any API route using the rate limiter middleware
1// src/lib/rate-limit.ts23import { Ratelimit } from "@upstash/ratelimit";4import { Redis } from "@upstash/redis";56// Create a rate limiter with 10 requests per 10 seconds7export const ratelimit = new Ratelimit({8 redis: Redis.fromEnv(),9 limiter: Ratelimit.slidingWindow(10, "10 s"),10 analytics: true,11 prefix: "@upstash/ratelimit",12});1314// Alternative: In-memory rate limiting for development15import { LRUCache } from "lru-cache";1617const tokenCache = new LRUCache<string, number>({18 max: 500,19 ttl: 60_000, // 1 minute20});2122export function rateLimit(ip: string, limit: number = 10) {23 const tokenCount = tokenCache.get(ip) || 0;2425 if (tokenCount >= limit) {26 return { success: false, remaining: 0 };27 }2829 tokenCache.set(ip, tokenCount + 1);30 return { success: true, remaining: limit - tokenCount - 1 };31}
Apply rate limiting to your API routes
1// src/app/api/your-route/route.ts23import { NextRequest, NextResponse } from "next/server";4import { ratelimit } from "@/lib/rate-limit";56export async function POST(request: NextRequest) {7 // Get client IP8 const ip = request.ip ??9 request.headers.get("x-forwarded-for") ??10 "127.0.0.1";1112 // Check rate limit13 const { success, limit, reset, remaining } = await ratelimit.limit(ip);1415 if (!success) {16 return NextResponse.json(17 { error: "Too many requests. Please try again later." },18 {19 status: 429,20 headers: {21 "X-RateLimit-Limit": limit.toString(),22 "X-RateLimit-Remaining": remaining.toString(),23 "X-RateLimit-Reset": reset.toString(),24 "Retry-After": Math.ceil((reset - Date.now()) / 1000).toString(),25 },26 }27 );28 }2930 // Process request normally31 return NextResponse.json({ success: true });32}
Configure different rate limits for different endpoints
1// src/lib/rate-limit.ts23import { Ratelimit } from "@upstash/ratelimit";4import { Redis } from "@upstash/redis";56const redis = Redis.fromEnv();78// Strict limit for auth endpoints9export const authLimiter = new Ratelimit({10 redis,11 limiter: Ratelimit.slidingWindow(5, "60 s"), // 5 per minute12 prefix: "ratelimit:auth",13});1415// Standard API limit16export const apiLimiter = new Ratelimit({17 redis,18 limiter: Ratelimit.slidingWindow(60, "60 s"), // 60 per minute19 prefix: "ratelimit:api",20});2122// Generous limit for read operations23export const readLimiter = new Ratelimit({24 redis,25 limiter: Ratelimit.slidingWindow(100, "60 s"), // 100 per minute26 prefix: "ratelimit:read",27});2829// Strict limit for write operations30export const writeLimiter = new Ratelimit({31 redis,32 limiter: Ratelimit.slidingWindow(20, "60 s"), // 20 per minute33 prefix: "ratelimit:write",34});
Rate limit by user ID instead of IP for authenticated endpoints
1// src/app/api/protected-route/route.ts23import { NextRequest, NextResponse } from "next/server";4import { auth } from "@/lib/auth";5import { ratelimit } from "@/lib/rate-limit";67export async function POST(request: NextRequest) {8 const session = await auth();910 if (!session?.user?.id) {11 return NextResponse.json(12 { error: "Unauthorized" },13 { status: 401 }14 );15 }1617 // Rate limit by user ID (more fair than IP)18 const { success, remaining } = await ratelimit.limit(19 `user:${session.user.id}`20 );2122 if (!success) {23 return NextResponse.json(24 { error: "Rate limit exceeded" },25 { status: 429 }26 );27 }2829 // Process request30 return NextResponse.json({31 success: true,32 remaining33 });34}