GuardAPI Logo
GuardAPI

Fix API Rate Limit Exhaustion in Next.js

Next.js API routes are sitting ducks for automated resource exhaustion. Without a sliding window or token bucket mechanism, an attacker can flood your serverless functions, spiking costs and inducing a DoS. You're basically handing over a blank check to anyone with a bash script. To secure this, you need a centralized state—like Redis—to track request frequency across distributed instances.

The Vulnerable Pattern

export default async function handler(req, res) {
  // VULNERABLE: No check on request frequency.
  // An attacker can call this 10,000 times a second to exhaust DB connections or API credits.
  const data = await db.performExpensiveQuery();
  return res.status(200).json(data);
}

The Secure Implementation

The secure implementation leverages a sliding window algorithm backed by Redis. Unlike local memory variables which reset on every serverless cold start, Redis provides a persistent, shared state for all incoming requests. We identify the client using the 'x-forwarded-for' header (ensure your proxy is trusted to prevent IP spoofing). If the 'success' flag is false, we terminate the execution early with an HTTP 429 status, shielding the expensive database logic from the load.

import { Ratelimit } from "@upstash/ratelimit";
import { Redis } from "@upstash/redis";

const redis = new Redis({ url: process.env.UPSTASH_REDIS_REST_URL, token: process.env.UPSTASH_REDIS_REST_TOKEN, });

// Create a new rate limiter: 10 requests per 10 seconds const ratelimit = new Ratelimit({ redis: redis, limiter: Ratelimit.slidingWindow(10, “10 s”), });

export default async function handler(req, res) { const identifier = req.headers[“x-forwarded-for”] || “anonymous”; const { success, limit, reset, remaining } = await ratelimit.limit(identifier);

res.setHeader(“X-RateLimit-Limit”, limit.toString()); res.setHeader(“X-RateLimit-Remaining”, remaining.toString()); res.setHeader(“X-RateLimit-Reset”, reset.toString());

if (!success) { return res.status(429).json({ error: “Too many requests. Slow down, script kiddie.” }); }

const data = await db.performExpensiveQuery(); return res.status(200).json(data); }

System Alert • ID: 1459
Target: Next.js API
Potential Vulnerability

Your Next.js API might be exposed to API Rate Limit Exhaustion

74% of Next.js apps fail this check. Hackers use automated scanners to find this specific flaw. Check your codebase before they do.

RUN FREE SECURITY DIAGNOSTIC
GuardLabs Engine: ONLINE

Free Tier • No Credit Card • Instant Report

Verified by Ghost Labs Security Team

This content is continuously validated by our automated security engine and reviewed by our research team. Ghost Labs analyzes over 500+ vulnerability patterns across 40+ frameworks to provide up-to-date remediation strategies.