grEEff.dev
WorkProcessPricingInsights
Start Your Project
Engineering

January 29, 2026

28 min

Ship a Production-Grade Next.js App with Rate Limiting + Bot Protection

Every unprotected Next.js app is a buffet for scrapers, credential stuffers, and AI training bots. This tutorial builds a defense layer with rate limiting, fingerprinting, bot detection, and WAF-style rules—all in middleware.

Pio Greeff

Pio Greeff

Founder & Lead Developer

Deep dive article

Ship a Production-Grade Next.js App with Rate Limiting + Bot Protection

Your API is getting hammered. You just don't know it yet.

Every unprotected Next.js app is a buffet for scrapers, credential stuffers, and AI training bots. They're hitting your endpoints right now—burning your Vercel bill, polluting your analytics, and scraping content you spent months creating.

This tutorial builds a defense layer that stops them. Rate limiting, fingerprinting, bot detection, and WAF-style rules—all in Next.js middleware.

No paid services. No vendor lock-in. Just code that works.



60-Second Quickstart

Test it:

That's it. Your API now fights back.


The Problem: You're Getting Scraped Right Now

Check your Vercel/analytics logs. You'll find:

What You'll SeeWhat It Actually Is
Thousands of requests from "empty" user-agentsScrapers that forgot to set headers
Requests from python-requests, axios, curlLazy bot operators
Same IP hitting /api/* 100x/minuteCredential stuffing or enumeration
Requests to /wp-admin, /.env, /config.phpVulnerability scanners (you're not even running PHP)
GPTBot, CCBot, anthropic-ai in user-agentAI training crawlers eating your content
Requests with no cookies, no JS executionHeadless browsers or raw HTTP clients

The cost is real:

  • Vercel charges by invocation. 100K bot requests = $15-40 depending on your plan.
  • Database connections exhausted. Your real users get 503s while bots hammer your API.
  • Content scraped and republished. Your blog posts appear on content farms within hours.
  • Rate limits on third-party APIs consumed. Bots trigger your OpenAI/Stripe/SendGrid calls.

Most Next.js apps ship with zero protection. Middleware runs on every request—it's the perfect place to fix this.


Before vs After: The Same Attack, Two Apps

Attack: A scraper hits your /api/users endpoint to enumerate valid usernames.

❌ Unprotected Next.js App

What happens:


✅ Protected Next.js App

Same endpoint, but with our middleware:

What happens:

The difference: 10,000x fewer successful requests. Zero data exfiltration. Automatic escalation.


When NOT to Use This

Middleware-based protection has limits. Know when to use something else.

SituationBetter Alternative
DDoS attacks (100K+ req/sec)You need Cloudflare/AWS Shield at the edge. Middleware can't stop traffic that saturates your origin.
Sophisticated bot farmsResidential proxies + browser fingerprint rotation defeats IP-based limits. Use CAPTCHA or proof-of-work.
Authenticated API abusePer-user rate limits need server-side state tied to auth tokens, not IP/fingerprint.
Compliance requirements (PCI, SOC2)You need a real WAF with audit logs, not DIY middleware.
Multi-region deploymentsVercel Edge + KV works, but managing distributed rate limit state is complex. Consider Upstash.

Use this middleware when:

  • You're on Vercel/similar and need quick protection
  • Traffic is moderate (under 10K req/min)
  • You want to block obvious bots and lazy scrapers
  • You need defense-in-depth behind Cloudflare
  • Budget for paid WAF is $0

This stops 90% of attacks with 10% of the effort.


Architecture Overview

Each layer can block independently. A request must pass all four to reach your app.


Part 1: Rate Limiting Middleware

We use a sliding window algorithm—it's more accurate than fixed windows and prevents the "boundary burst" problem.

Why sliding window over token bucket?

Token bucket allows bursts—an attacker can dump 100 requests instantly, then wait. Sliding window spreads the limit evenly across time.

Why escalating blocks?

First offense: 1 minute. Second: 2 minutes. Third: 4 minutes. Legitimate users who accidentally hit limits recover quickly. Attackers face exponentially increasing delays.


Part 2: Request Fingerprinting

IP addresses aren't enough. Users behind NAT share IPs. Attackers rotate through proxies. We need a stable identifier that survives IP changes.

Why fingerprint instead of just IP?

  1. NAT/CGNAT: Thousands of users share one IP (mobile carriers, corporate networks).
  2. VPNs: Millions of users share VPN exit nodes. Blocking the IP blocks everyone.
  3. Rotating proxies: Attackers change IPs constantly. Fingerprint stays stable.

The fingerprint combines IP + headers to create a more unique identifier. It's not perfect (sophisticated attackers can rotate headers too), but it catches 95% of automated traffic.


Part 3: Bot Detection

Most bots are lazy. They don't set proper headers, use known automation tools, or exhibit inhuman behavior patterns.

Why separate good bots?

GoogleBot needs to crawl your site for SEO. Blocking it tanks your search rankings. The isGoodBot check lets search engines and social media previews through while blocking scrapers.

Confidence scoring:

Instead of binary yes/no, we score confidence. A request with python-requests user-agent AND missing Accept-Language is definitely a bot (0.9+). A request with just a generic Accept header might be a misconfigured browser (0.2).


Part 4: WAF-Style Rules

Block obviously malicious requests before they hit your app.

What this catches:

  • WordPress/PHP probes hitting your Node app
  • Config file scans (.env, .git)
  • SQL injection in query strings
  • XSS payloads in URLs
  • Log4j/SSTI attempts in headers
  • Path traversal attacks

What this doesn't catch:

  • Sophisticated attacks with encoded payloads
  • Zero-day vulnerabilities
  • Business logic abuse

For those, you need a real WAF (Cloudflare, AWS WAF, etc.).


Part 5: API Route Protection

A decorator for API routes that adds per-endpoint rate limiting and abuse detection.


Part 6: Full Middleware Stack

Tie it all together in middleware.ts:


Part 7: Testing Your Defenses

A test suite to verify your protection actually works.

Run with:

Expected output:


Cost & Performance Impact

Latency Overhead

ComponentAdded LatencyNotes
WAF rules (regex checks)~0.5ms40 patterns, optimized regexes
Bot detection~0.2msHeader checks + pattern matching
Fingerprinting~0.1msSHA256 hash of headers
Rate limit check (LRU cache)~0.05msIn-memory, O(1) lookup
Total~1msNegligible vs. network latency

Memory Usage

ComponentMemoryNotes
LRU cache (10K entries)~5MBPer rate limiter instance
4 rate limiters~20MBpages, api, auth, heavy
Regex patterns (compiled)~1MBCompiled once at startup
Total~25MBWell within Vercel limits

Vercel Cost Impact

ScenarioBefore ShieldAfter ShieldSavings
100K bot requests/month$15-40$0.50 (blocked at middleware)97%
DDoS attempt (1M requests)$150-400$5-10 (most blocked)97%
Normal traffic (50K/month)$7-20$7-21 (+1ms latency)~0%

The math: Blocked requests still invoke middleware (you pay for the invocation), but they don't hit your database, APIs, or external services. The real savings come from not triggering expensive downstream operations.


Tuning Guide

Rate Limits

Endpoint TypeRecommended LimitBlock DurationNotes
Public pages100/min1 minGenerous for real users
API routes30/min5 minTighter for data endpoints
Auth endpoints5/15min1 hourPrevent credential stuffing
Search/heavy ops10/min10 minProtect expensive operations
Webhooks100/min1 minThird-party services need headroom

Bot Detection Thresholds

ConfidenceActionExample
< 0.3AllowMissing one header
0.3 - 0.5Log + allowSuspicious but not definite
0.5 - 0.8Challenge or blockMultiple signals
> 0.8Block + banDefinite bot

When to Escalate to a Real WAF

SignalAction
> 10K blocked requests/dayConsider Cloudflare (free tier)
Sophisticated attacks bypassing rulesUpgrade to Cloudflare Pro or AWS WAF
Compliance requirements (SOC2, PCI)You need audit logs and managed rules
Geographic attacksUse geo-blocking at the edge

Common Attacks & Responses

AttackDetectionResponse
Credential stuffingHigh volume to /api/auth, different usernamesAuth rate limit (5/15min), require CAPTCHA after 3 failures
Content scrapingSequential page requests, no JS executionBot detection blocks, consider JS challenge
API enumerationIncrementing IDs, rapid 404sRate limit + monitor 404 rate per fingerprint
Search abuseHigh volume search queriesHeavy rate limit (10/min), require auth for API
AI training botsGPTBot, CCBot user-agentsBlock by user-agent, add to robots.txt
Vulnerability scanning/wp-admin, /.env, SQL patternsWAF blocks, 24hr ban for critical attempts
DDoS (application layer)Sustained high volume from few IPsRate limit + escalating blocks, consider edge protection

robots.txt for AI Crawlers

While you're at it, tell AI training bots to stay away:

Note: robots.txt is advisory. Ethical bots respect it; scrapers ignore it. That's why you need the middleware.


Dependencies

That's it. One dependency. The rest is standard Next.js.


What This Doesn't Cover

This is defense-in-depth, not a fortress. You'll still need:

  1. Edge protection (Cloudflare/AWS Shield) — Stops DDoS before it hits your origin
  2. CAPTCHA integration — For high-value actions (signup, checkout)
  3. Proper authentication — JWTs, session management, CSRF protection
  4. Database rate limiting — Protect against authenticated abuse
  5. Monitoring/alerting — Know when you're under attack
  6. Geo-blocking — If your business is US-only, block other regions at the edge

Each is a tutorial on its own.


The Bottom Line

Every unprotected Next.js app is getting scraped. Your Vercel bill is higher than it should be. Your content is being stolen. Your APIs are being abused.

This middleware stack:

  • Rate limits with escalating blocks for repeat offenders
  • Fingerprints requests to track abusers across IP changes
  • Detects bots through user-agent patterns and missing headers
  • Blocks attacks with WAF-style rules for SQL injection, XSS, and suspicious paths

It adds ~1ms latency and catches 90% of automated abuse. For the other 10%, you need Cloudflare.

Build it. Test it. Ship it. Check your logs in a week—you'll be surprised what you catch.


Found this useful?

Share it with your network

Starter Kits

Build the architecture behind this article

Ship faster with production-ready Next.js + Cloudflare starter kits. Pick one path, or take the full bundle.