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
| Setting | Value | Description |
|---|---|---|
| Window | 5 minutes | Time window for rate limiting |
| Max Requests | 200 | Maximum requests per window per IP |
Environment Variables
| Variable | Description | Default |
|---|---|---|
NEXT_PUBLIC_CI | Disables rate limiting when set | - |
BETTER_AUTH_RATE_LIMIT_STORAGE | Storage backend: database or secondary-storage | database |
Environment-Based Enablement
Rate limiting is enabled by default and only disabled in CI:
| Environment | Rate Limiting |
|---|---|
| Production | Enabled |
| Development | Enabled |
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.tsConfiguration 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.tsimport { 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 minutesconst MAX = 200; // 200 requests per windowStricter Rate Limiting
For stricter protection, reduce the values:
const WINDOW_SECONDS = 1 * 60; // 1 minuteconst MAX = 50; // 50 requests per minuteTesting
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