Features
Docs
CLI
Benchmarks
Examples

© 2024 MoroJs

Rate Limiting

Protect your APIs from abuse. Configure limits per route, user, or IP. Simple setup, powerful protection.

Rate Limiting That Protects

Add rate limiting to any route with one line.
Protect against abuse, ensure fair usage, and maintain performance.

It's This Simple

Add rate limiting with one line

typescript

1app.post('/users')
2  .rateLimit({ requests: 10, window: 60000 }) // 10 requests per minute
3  .handler(() => {
4    return createUser();
5  });

Why Rate Limiting Matters

Without rate limiting, your API is vulnerable to abuse, DDoS attacks, and unfair usage. With rate limiting, you control access and protect resources.

Traditional rate limiting requires middleware setup, storage configuration, and manual tracking. We handle that automatically.

Without Rate Limiting

  • Vulnerable to abuse and DDoS
  • Unfair resource usage
  • Manual tracking required
  • Complex middleware setup

With MoroJS

  • Automatic abuse protection
  • Fair usage enforcement
  • One-line setup
  • Flexible per-route configuration

It's This Easy

Configure limits per route. Different limits for different endpoints.

Different limits for different endpoints

typescript

1// Authentication - strict limits
2app.post('/auth/login')
3  .rateLimit({ requests: 5, window: 900000 }) // 5 attempts per 15 minutes
4  .handler(() => authenticateUser());
5
6// Public API - higher limits
7app.get('/api/public')
8  .rateLimit({ requests: 1000, window: 3600000 }) // 1000 per hour
9  .handler(() => getPublicData());

Why It Makes Sense

Protection

Protect against abuse, DDoS attacks, and resource exhaustion.

Fair Usage

Ensure fair resource distribution. Different limits for different users.

Simple

One line per route. Automatic tracking. Custom keys supported.

How It Works

MoroJS rate limiting tracks requests based on a key (IP, user ID, or custom) within a time window. When the limit is exceeded, requests are automatically rejected with a 429 status code and helpful headers.

Configuration

Basic Rate Limiting

typescript

1import { createApp, z } from '@morojs/moro';
2
3const app = createApp();
4
5// Rate limiting with chainable API
6app.post('/users')
7  .body(z.object({
8    name: z.string().min(2),
9    email: z.string().email()
10  }))
11  .rateLimit({ requests: 10, window: 60000 }) // 10 requests per minute
12  .handler(({ body }) => {
13    return { success: true, data: createUser(body) };
14  });

Different Limits for Different Endpoints

typescript

1// Authentication - strict limits
2app.post('/auth/login')
3  .rateLimit({ requests: 5, window: 900000 }) // 5 attempts per 15 minutes
4  .handler(() => authenticateUser());
5
6// Public API - higher limits
7app.get('/api/public')
8  .rateLimit({ requests: 1000, window: 3600000 }) // 1000 per hour
9  .handler(() => getPublicData());
10
11// File uploads - very strict
12app.post('/api/upload')
13  .rateLimit({ requests: 10, window: 3600000 }) // 10 uploads per hour
14  .handler(() => uploadFile());

Advanced Configuration

For advanced use cases, you can configure custom rate limit keys (by user ID, API key, etc.), dynamic limits based on user plans, and custom error responses.

Custom Rate Limit Keys

typescript

1// Rate limit by user ID
2app.get('/api/user-data', {
3  middleware: [authMiddleware],
4  rateLimit: {
5    requests: 1000,
6    window: 3600000, // 1 hour
7    key: (ctx) => `user:${ctx.context.user.id}`
8  },
9  handler: ({ context }) => {
10    return getUserData(context.user.id);
11  }
12});
13
14// Rate limit by API key
15app.get('/api/premium', {
16  rateLimit: {
17    requests: (ctx) => {
18      const apiKey = ctx.headers['x-api-key'];
19      const user = getUserByApiKey(apiKey);
20      return user.plan === 'premium' ? 10000 : 1000;
21    },
22    window: 3600000,
23    key: (ctx) => `apikey:${ctx.headers['x-api-key']}`
24  },
25  handler: () => getPremiumData()
26});

Custom Error Responses

typescript

1app.post('/api/sensitive', {
2  rateLimit: {
3    requests: 10,
4    window: 3600000,
5    onLimitReached: (ctx, info) => {
6      return {
7        status: 429,
8        headers: {
9          'Retry-After': info.resetTime.toString(),
10          'X-RateLimit-Limit': info.limit.toString(),
11          'X-RateLimit-Remaining': '0',
12          'X-RateLimit-Reset': info.resetTime.toString()
13        },
14        body: {
15          success: false,
16          error: 'RATE_LIMIT_EXCEEDED',
17          message: `Too many requests. Try again in ${info.resetTime} seconds.`
18        }
19      };
20    }
21  },
22  handler: () => processSensitiveData()
23});

Next Steps