Documentation

Rate Limiting

Learn how to set up and use Upstash Redis for efficient rate limiting

Dirstarter uses Upstash Redis with their @upstash/ratelimit package for efficient rate limiting. This combination provides a serverless-friendly solution for protecting your APIs and routes from abuse.

This integration is optional. If you don't want to use rate limiting, you can skip this section.

Upstash Redis

Upstash Redis is a serverless Redis database that offers:

  • Serverless architecture
  • Global distribution
  • TypeScript support
  • Built-in rate limiting
  • Edge compatibility
  • Pay-per-use pricing

Setup

  1. Create an Upstash account at upstash.com
  2. Create a new Redis database
  3. Get your Redis URL and token from the dashboard
  4. Add the following environment variables:
.env
REDIS_REST_URL=your_redis_url
REDIS_REST_TOKEN=your_redis_token

Alternative Redis Hosting

While Upstash is our recommended choice, you can use any Redis provider that supports the REST API. Here are some popular options:

  1. Self-hosted Redis
  2. Redis Cloud
  3. DigitalOcean Redis

When using a non-Upstash Redis provider, make sure it supports the REST API and has proper authentication. Some providers might require additional configuration or have different connection string formats.

Usage

The boilerplate provides a simple way to implement rate limiting:

services/redis.ts
import { Redis } from "@upstash/redis"
import { env } from "~/env"
 
export const redis = new Redis({
  url: env.REDIS_REST_URL,
  token: env.REDIS_REST_TOKEN,
})

Implementation

The boilerplate includes pre-configured rate limiters for different actions:

lib/rate-limiter.ts
import { Ratelimit } from "@upstash/ratelimit"
import { redis } from "~/services/redis"
 
const limiters = {
  submission: new Ratelimit({
    redis,
    analytics: true,
    limiter: Ratelimit.slidingWindow(3, "24 h"), // 3 attempts per day
  }),
 
  report: new Ratelimit({
    redis,
    analytics: true,
    limiter: Ratelimit.slidingWindow(3, "1 h"), // 3 attempts per hour
  }),
 
  newsletter: new Ratelimit({
    redis,
    analytics: true,
    limiter: Ratelimit.slidingWindow(3, "24 h"), // 3 attempts per day
  }),
 
  claim: new Ratelimit({
    redis,
    analytics: true,
    limiter: Ratelimit.slidingWindow(5, "1 h"), // 5 attempts per hour
  }),
}

Use the rate limiter in your server actions:

app/actions/submit.ts
import { isRateLimited } from "~/lib/rate-limiter"
 
export async function submitAction() {
  const ip = await getIP()
  const rateLimitKey = `submission:${ip}`
  
  if (await isRateLimited(rateLimitKey, "submission")) {
    throw new Error("Too many submissions. Please try again later.")
  }
  
  // Your submission logic here
}
Edit on GitHub

Last updated on

On this page