typescriptintermediate
API Route Rate Limiting
Add rate limiting to Next.js API routes with sliding window, IP-based limits, and custom responses.
typescriptPress ⌘/Ctrl + Shift + C to copy
// app/api/lib/rate-limit.ts
import { NextRequest, NextResponse } from 'next/server';
interface RateLimitConfig {
maxRequests: number;
windowMs: number;
keyFn?: (req: NextRequest) => string;
message?: string;
}
interface Entry {
tokens: number;
lastRefill: number;
}
const store = new Map<string, Entry>();
// Cleanup old entries periodically
setInterval(() => {
const now = Date.now();
for (const [key, entry] of store) {
if (now - entry.lastRefill > 300_000) store.delete(key);
}
}, 60_000);
function rateLimit(config: RateLimitConfig) {
const {
maxRequests,
windowMs,
keyFn = (req) => req.headers.get('x-forwarded-for') ?? 'anonymous',
message = 'Too many requests, please try again later.',
} = config;
return (req: NextRequest): NextResponse | null => {
const key = keyFn(req);
const now = Date.now();
let entry = store.get(key);
if (!entry) {
entry = { tokens: maxRequests - 1, lastRefill: now };
store.set(key, entry);
return null; // Allow
}
// Token bucket refill
const elapsed = now - entry.lastRefill;
const refill = Math.floor((elapsed / windowMs) * maxRequests);
entry.tokens = Math.min(maxRequests, entry.tokens + refill);
entry.lastRefill = now;
if (entry.tokens <= 0) {
return NextResponse.json(
{ error: message },
{
status: 429,
headers: {
'Retry-After': String(Math.ceil(windowMs / 1000)),
'X-RateLimit-Limit': String(maxRequests),
'X-RateLimit-Remaining': '0',
},
},
);
}
entry.tokens--;
return null; // Allow
};
}
// app/api/data/route.ts
const limiter = rateLimit({ maxRequests: 30, windowMs: 60_000 });
export async function GET(req: NextRequest) {
const limited = limiter(req);
if (limited) return limited;
return NextResponse.json({ data: 'Hello from rate-limited API!' });
}
export async function POST(req: NextRequest) {
const limited = limiter(req);
if (limited) return limited;
const body = await req.json();
return NextResponse.json({ received: body });
}
export { rateLimit };Use Cases
- API abuse prevention
- Fair usage enforcement
- DDoS mitigation
Tags
Related Snippets
Similar patterns you can reuse in the same workflow.
typescriptadvanced
Webhook Handler with Signature Verification
Handle incoming webhooks with signature verification and idempotent processing.
Best for: payment webhooks
#nextjs#webhooks
typescriptintermediate
Type-Safe API Route Handler
Next.js App Router route handler with input validation, typed responses, and proper error handling.
Best for: CRUD API endpoints
#api#route-handler
typescriptintermediate
Next.js Route Handlers (API Routes)
Build RESTful API endpoints using Next.js App Router route handlers with typed responses.
Best for: Building REST APIs within a Next.js application
#nextjs#api
typescriptadvanced
Next.js Middleware for Authentication
Protect routes with Next.js middleware using token verification and role-based redirects.
Best for: Protecting authenticated routes at the edge
#nextjs#middleware