Rate Limiting

Protect authentication endpoints from abuse

Rate limiting protects your authentication endpoints from brute force attacks and abuse by limiting the number of requests within a time window.

Overview

The rate limiting configuration is automatically applied to all Better Auth API endpoints.

Configuration

Default Settings

SettingValueDescription
Window5 minutesTime window for rate limiting
Max Requests200Maximum requests per window per IP

Environment Variables

VariableDescriptionDefault
NEXT_PUBLIC_CIDisables rate limiting when set-
BETTER_AUTH_RATE_LIMIT_STORAGEStorage backend: database or secondary-storagedatabase

Environment-Based Enablement

Rate limiting is enabled by default and only disabled in CI:

EnvironmentRate Limiting
ProductionEnabled
DevelopmentEnabled
CI/CD (NEXT_PUBLIC_CI set)Disabled
const IS_RATE_LIMIT_ENABLED = !process.env.NEXT_PUBLIC_CI;

Implementation

Location

packages/better-auth/src/plugins/rate-limit.ts

Configuration Object

export const rateLimitConfig = {
enabled: IS_RATE_LIMIT_ENABLED,
window: WINDOW_SECONDS, // 5 minutes
max: MAX, // 200 requests
...getRateLimitStorageConfig(),
};

Storage Backends

The rate limit data can be stored in:

  • database (default) - Uses PostgreSQL via Drizzle, works across instances
  • secondary-storage - External stores like Redis/Upstash
const RATE_LIMIT_STORAGE = z
.enum(['database', 'secondary-storage'])
.default('database')
.parse(process.env.BETTER_AUTH_RATE_LIMIT_STORAGE);

Integration with Better Auth

The rate limit config is applied in the main auth configuration:

// packages/better-auth/src/auth.ts
import { rateLimitConfig } from './plugins/rate-limit';
export const auth = betterAuth({
// ... other config
rateLimit: rateLimitConfig,
});

Customization

To customize rate limiting, modify packages/better-auth/src/plugins/rate-limit.ts:

const WINDOW_SECONDS = 5 * 60; // 5 minutes
const MAX = 200; // 200 requests per window

Stricter Rate Limiting

For stricter protection, reduce the values:

const WINDOW_SECONDS = 1 * 60; // 1 minute
const MAX = 50; // 50 requests per minute

Testing

Rate limiting is disabled in CI environments to prevent test flakiness. Set NEXT_PUBLIC_CI=true in your CI configuration.

Monitoring

Monitor rate limit events in your application logs. When a client exceeds the rate limit, Better Auth returns a 429 Too Many Requests response.

Custom Rate Limiting

For rate limiting outside of Better Auth endpoints (API routes, server actions, file uploads), use the database-backed rate limit service.

See: Rate Limit Service Documentation

import { createRateLimitService } from '@kit/database/rate-limit';
const rateLimitService = createRateLimitService();
const result = await rateLimitService.limit('api:upload:user123', {
windowSeconds: 60,
max: 10,
});
if (!result.success) {
return new Response('Rate limited', { status: 429 });
}

Next: One-Time Token Plugin