Rate Limiting

Tiered API rate limiting with Upstash Redis. Gracefully degrades to allow-all in development.

Protect API routes from abuse with 3 pre-configured tiers powered by Upstash Redis's sliding window algorithm. Setup takes ~5 minutes.

What's Included

FilePurpose
lib/features/rate-limit.tsrateLimit(req, tier) — returns { success, limit, remaining, reset }

Tiers

TierRequestsWindowUse Case
strict101 minuteAuth endpoints (login, signup, password reset)
standard301 minuteGeneral CRUD API routes
lenient601 minuteRead-heavy endpoints (search, listings)

When UPSTASH_REDIS_REST_URL is not set, the limiter logs a warning and allows all requests through — safe for local development.

Setup

1

Install dependencies

pnpm add @upstash/ratelimit @upstash/redis
2

Add environment variables

UPSTASH_REDIS_REST_URL="https://your-region.upstash.io"
UPSTASH_REDIS_REST_TOKEN="your-token"

Create a Redis database at upstash.com (free tier: 10,000 req/day). Copy the REST URL and token from the database console.

3

Add to API routes

import { rateLimit } from "@/lib/features/rate-limit"

export async function POST(req: Request) {
  const rl = await rateLimit(req, "standard")
  if (!rl.success) {
    return Response.json(
      { success: false, error: "Too many requests. Please try again later." },
      {
        status: 429,
        headers: {
          "X-RateLimit-Limit": String(rl.limit),
          "X-RateLimit-Remaining": String(rl.remaining),
          "X-RateLimit-Reset": String(rl.reset),
        },
      }
    )
  }

  // ... your route logic
}

Environment Variables

VariableRequiredDescription
UPSTASH_REDIS_REST_URLNo*Upstash Redis REST URL
UPSTASH_REDIS_REST_TOKENNo*Upstash Redis REST token

*Not required for development. Rate limiting is bypassed when not set (with a console warning).

Return Value

{
  success: boolean   // true = request allowed
  limit: number      // max requests in the window
  remaining: number  // requests remaining in current window
  reset: number      // Unix timestamp when the window resets
}

Verification

  1. Add rate limiting to any API route
  2. Hit it rapidly in a loop (e.g., for i in {1..15}; do curl localhost:3000/api/route; done)
  3. After exceeding the tier limit, you should receive 429 with X-RateLimit-* headers
  4. Wait for the window to reset — requests allowed again
  5. Remove env vars locally — confirm requests pass through with a console warning

Demo Mode — Explore freely. Some actions are restricted. demo@launchfst.dev / demo1234

Get LaunchFst →