Rate Limiting

This guide explains how rate limiting is implemented in our application using Upstash Redis to prevent abuse and ensure fair usage of resources.

Setup

Prerequisites

  • Upstash Redis account
  • Redis connection details
  • .env.local configuration

Environment Variables

# Upstash Redis Configuration
UPSTASH_REDIS_REST_URL=your_redis_url
UPSTASH_REDIS_REST_TOKEN=your_redis_token

Implementation

Redis Client Setup

Configure the Upstash Redis client in lib/upstash.ts:

import { Redis } from "@upstash/redis"

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

Rate Limiter Configuration

Set up rate limiting with sliding window algorithm:

import { Ratelimit } from "@upstash/ratelimit"
import { redis } from "@/lib/upstash"

const ratelimit = new Ratelimit({
  redis,
  limiter: Ratelimit.slidingWindow(
    RATE_LIMIT_5,    // 5 requests
    "1 m"           // per 1 minute
  ),
})

Usage Examples

Server Action Rate Limiting

Implementing rate limiting in server actions:

export const createUserAction = async () => {
  try {
    const { user } = await getCurrentUser()
    if (!user) {
      throw new AuthenticationError()
    }

    // Create unique identifier for this action
    const identifier = `ratelimit:create-user:${user.id}`
    
    // Check rate limit
    const { success } = await ratelimit.limit(identifier)
    if (!success) {
      throw new RateLimitError()
    }

    // Continue with action...
  } catch (error) {
    // Handle errors...
  }
}

API Route Rate Limiting

Protecting API routes with rate limiting:

export async function POST(req: NextRequest) {
  try {
    const { user } = await getCurrentUser()
    if (!user) {
      return responses.notAuthenticatedResponse()
    }

    const identifier = `ratelimit:api-route:${user.id}`
    const { success } = await ratelimit.limit(identifier)

    if (!success) {
      return responses.tooManyRequestsResponse()
    }

    // Continue with API logic...
  } catch (error) {
    return responses.internalServerErrorResponse()
  }
}

Common Use Cases

Image Uploads

Limit the number of image uploads per user per minute

Authentication

Prevent brute force attacks on authentication endpoints

API Endpoints

Control access rates to public and private API endpoints

Form Submissions

Prevent spam by limiting form submission frequency

Best Practices

Implementation

  • Use unique identifiers per action
  • Include user ID in rate limit keys
  • Set appropriate time windows
  • Handle rate limit errors gracefully

Security

  • Implement rate limiting early in request pipeline
  • Use different limits for different actions
  • Monitor rate limit usage
  • Provide clear feedback to users