> ## Documentation Index
> Fetch the complete documentation index at: https://docs.jtbdos.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Rate Limiting

> Protecting your API routes from abuse.

export const Authors = ({data}) => {
  const baseUrl = typeof window !== 'undefined' && window.location.origin.includes('localhost') ? '' : 'https://raw.githubusercontent.com/haydenbleasel/JTBDOS/refs/heads/main/docs';
  return <div style={{
    marginBottom: '3rem',
    display: 'flex',
    flexDirection: 'column',
    gap: '0.5rem'
  }}>
      <span style={{
    color: 'rgb(107, 114, 128)',
    fontSize: '0.875rem'
  }}>Co-authored by</span>
      <div style={{
    display: 'flex',
    flexWrap: 'wrap',
    alignItems: 'center',
    gap: '0.5rem'
  }}>
        {data.map(author => <div key={author.name} style={{
    padding: '0.75rem',
    paddingRight: '1rem',
    display: 'inline-flex',
    alignItems: 'center',
    gap: '0.75rem',
    fontWeight: 'normal',
    position: 'relative',
    ringWidth: '2px',
    ringColor: 'transparent',
    borderRadius: '0.75rem',
    backgroundColor: 'white',
    border: '1px solid rgba(0,0,0,0.1)',
    overflow: 'hidden'
  }}>
            <div style={{
    position: 'relative'
  }}>
              <div style={{
    overflow: 'hidden',
    border: '1px solid #e5e7eb',
    borderRadius: '9999px',
    width: '2rem',
    height: '2rem'
  }}>
                <img style={{
    margin: 0,
    width: '100%',
    height: '100%',
    objectFit: 'cover'
  }} src={`${baseUrl}/images/authors/${author.company.id}/${author.user.id}.jpg`} alt="" width={32} height={32} />
              </div>
              <div style={{
    position: 'absolute',
    border: '1px solid white',
    overflow: 'hidden',
    borderRadius: '9999px',
    objectFit: 'cover',
    width: '1rem',
    height: '1rem',
    right: '-0.25rem',
    bottom: '-0.25rem'
  }}>
                <img style={{
    margin: 0,
    width: '100%',
    height: '100%',
    objectFit: 'cover'
  }} src={`${baseUrl}/images/authors/${author.company.id}/logo.jpg`} alt="" width={16} height={16} />
              </div>
            </div>
            <div style={{
    display: 'flex',
    flexDirection: 'column'
  }}>
              <span style={{
    fontWeight: 600,
    lineHeight: 1.25,
    fontSize: '13px',
    letterSpacing: '-0.01em'
  }}>
                {author.user.name}
              </span>
              <span style={{
    color: 'rgb(107, 114, 128)',
    lineHeight: 1.25,
    fontSize: '11px'
  }}>
                {author.company.name}
              </span>
            </div>
          </div>)}
      </div>
    </div>;
};

<Authors
  data={[{
user: {
name: 'Hayden Bleasel',
id: 'haydenbleasel',
},
company: {
name: 'JTBDOS',
id: 'JTBDOS',
},
}, {
user: {
name: 'Fahreddin Özcan',
id: 'fahreddin',
},
company: {
name: 'Upstash',
id: 'upstash',
},
}]}
/>

<Frame>
  <img src="https://mintlify.s3.us-west-1.amazonaws.com/thrv-c7d92728/images/rate-limit.png" alt="" />
</Frame>

Modern applications need rate limiting to protect against abuse, manage resources efficiently, and enable tiered API access. Without rate limiting, your application is vulnerable to brute force attacks, scraping, and potential service disruptions from excessive usage.

JTBDOS has a `rate-limit` package powered by [`@upstash/ratelimit`](https://github.com/upstash/ratelimit-js), a connectionless (HTTP-based) rate limiting library designed specifically for serverless and edge environments.

## Setting up

Rate limiting is enabled for the `web` package contact form automatically by the existence of a `UPSTASH_REDIS_REST_URL` and `UPSTASH_REDIS_REST_TOKEN` environment variable. If enabled, the contact form will limit the number of requests to 1 per day per IP address.

To get your environment variables, you can sign up at [Upstash Console](https://console.upstash.com) and create a Redis KV database. You can then find the REST URL and REST token in the database details page.

You can then paste these environment variables each of the [environment variables](/env) files.

## Adding rate limiting

You can add rate limiting to your API routes by using the `createRateLimiter` function. For example, to limit the number of AI requests to 10 per 10 seconds per IP address, you can do something like this:

```ts apps/app/api/chat/route.ts
import { currentUser } from '@repo/auth/server';
import { createRateLimiter, slidingWindow } from '@repo/rate-limit';

export const GET = async (request: NextRequest) => {
  const user = await currentUser();

  const rateLimiter = createRateLimiter({
    limiter: slidingWindow(10, '10 s'),
  });

  const { success } = await rateLimiter.limit(`ai_${user?.id}`);

  if (!success) {
    return new Response(
      JSON.stringify({ error: "Too many requests" }), 
      { status: 429 }
    );
  }
};
```

## Configuration

The `rate-limit` package connects to an [Upstash Redis](https://upstash.com/docs/redis/overall/getstarted) database and automatically limits the number of requests to your API routes.

The default rate limiting configuration allows 10 requests per 10 seconds per identifier. `@upstash/ratelimit` also has other rate limiting algorithms such as:

* Fixed Window
* Sliding Window
* Token Bucket

You can learn more about the different rate limiting strategies other features in the [Upstash documentation](https://upstash.com/docs/redis/sdks/ratelimit-ts/algorithms).

```ts packages/rate-limit/index.ts
export const ratelimit = new Ratelimit({
  redis,
  limiter: Ratelimit.slidingWindow(10, "10 s"),
  prefix: "JTBDOS",
})
```

## Usage

You can use rate limiting in any API Route by importing it from the `rate-limit` package. For example:

```typescript apps/api/app/ratelimit/upstash/route.ts {7}
import { ratelimit } from "@repo/rate-limit";

export const GET = async (request: NextRequest) => {
  // Use any identifier like username, API key, or IP address
  const identifier = "your-identifier";
  
  const { success, limit, remaining } = await ratelimit.limit(identifier);
  
  if (!success) {
    return new Response(
      JSON.stringify({ error: "Too many requests" }), 
      { status: 429 }
    );
  }
  
  // Continue with your API logic
};
```

## Analytics

Upstash Ratelimit provides built-in analytics capabilities through the dashboard on [Upstash Console](https://console.upstash.com).  When enabled, Upstash collects information about:

* Hourly request patterns
* Identifier usage
* Success and failure rates

To enable analytics for your rate limiting, pass the `analytics` configuration to rate limit client:

```typescript packages/security/index.ts
export const ratelimit = new Ratelimit({
  redis,
  limiter: Ratelimit.slidingWindow(10, "10 s"),
  prefix: "JTBDOS",
  analytics: true, // Enable Upstash analytics
})
```

### Dashboard

If the analytics is enabled, you can find information about how many requests were made with which identifiers and how many of the requests were blocked from the [Rate Limit dashboard in Upstash Console](https://console.upstash.com/ratelimit).

To find to the dashboard, simply click the three dots and choose the **Rate Limit Analytics** tab:

<Frame>
  <img src="https://mintlify.s3.us-west-1.amazonaws.com/thrv-c7d92728/images/upstash-ratelimit-navbar.png" alt="Upstash Rate Limit Navbar" />
</Frame>

In the dashboard, you can find information on how many requests were accepted, how many were blocked and how many were received in total. Additionally, you can see requests over time; top allowed, rate limited and denied requests.

<Frame>
  <img src="https://mintlify.s3.us-west-1.amazonaws.com/thrv-c7d92728/images/upstash-ratelimit-dashboard.png" alt="Upstash Rate Limit Dashboard" />
</Frame>

## Best Practices

<Steps>
  <Step title="Choose Appropriate Identifiers">
    Use meaningful identifiers for rate limiting like:

    * User IDs for authenticated requests
    * API keys for external integrations
    * IP addresses for public endpoints
  </Step>

  <Step title="Configure Rate Limits">
    Consider your application's requirements and resources when setting limits. Start conservative and adjust based on usage patterns.
  </Step>

  <Step title="Implement Error Handling">
    Always return appropriate error responses when rate limits are exceeded. Include information about when the limit will reset if possible.
  </Step>

  <Step title="Monitor and Adjust">
    Use the analytics feature to monitor rate limit hits and adjust limits as needed based on actual usage patterns.
  </Step>
</Steps>

## Further Information

`@upstash/ratelimit` also provides several advanced features:

* **Caching**: Use in-memory caching to reduce Redis calls for blocked identifiers
* **Custom Timeouts**: Configure request timeout behavior
* **Multiple Limits**: Apply different rate limits based on user tiers
* **Custom Rates**: Adjust rate limiting based on batch sizes or request weight
* **Multi-Region Support**: Distribute rate limiting across multiple Redis instances for global applications

For detailed information about these features and their implementation, refer to the [Upstash Ratelimit documentation](https://upstash.com/docs/redis/sdks/ratelimit-ts/overview).
