Our review
Provides guidance on designing and implementing rate limiting using various algorithms including Token Bucket, Leaky Bucket, Fixed Window, Sliding Window Log, and Sliding Window Counter with Redis and Node.js examples.
Strengths
- Covers multiple algorithms with clear diagrams
- Provides Redis Lua script and Node.js middleware implementations
- Includes tiered and dynamic rate limiting strategies
- Practical code examples for immediate use
Limitations
- Assumes Redis as the backing store; no in-memory or other store examples
- Does not cover distributed rate limiting coordination
- Code examples are in Node.js only, limiting language portability
When designing API rate limiting for a web service, especially when using Redis and Node.js.
When you need a rate limiting solution that is language-agnostic or does not require Redis, or when dealing with simple in-memory rate limiting without persistence.
Security analysis
SafeThe skill provides educational content and code examples for rate limiting design. It does not include any destructive commands, data exfiltration, or execution of external scripts. The code snippets are for illustration only and do not pose a risk.
No concerns found
Examples
Implement a token bucket rate limiter using Redis Lua script for my Express API.Set up tiered rate limiting for free, basic, and pro users in my Node.js app.Implement a sliding window counter rate limiter with Redis and Node.js.name: "rate-limit" description: "레이트 리밋 설계 가이드를 실행합니다." user-invocable: true
Rate Limiting Skill
레이트 리밋 설계 가이드를 실행합니다.
레이트 리밋 알고리즘
Token Bucket
버킷에 토큰이 일정 속도로 추가
요청 시 토큰 소비
토큰 없으면 거부
┌─────────────┐
│ ○ ○ ○ ○ ○ │ ← 토큰 추가 (초당 10개)
│ Bucket │
└──────┬──────┘
↓ 요청당 1토큰 소비
[Request]
장점: 버스트 허용, 평균 속도 제한
구현: Redis + Lua Script
Leaky Bucket
요청이 버킷에 쌓임
일정 속도로 처리
버킷 넘치면 거부
[Request]
↓
┌─────────────┐
│ ░ ░ ░ ░ ░ │ ← 큐 (고정 크기)
└──────┬──────┘
↓ 일정 속도로 처리
[Processed]
장점: 일정한 출력 속도
단점: 버스트 불가
Fixed Window
고정 시간 창에서 요청 수 제한
|----60초----|----60초----|
| 100 요청 | 100 요청 |
|____________|____________|
단점: 경계에서 2배 버스트 가능
(59초에 100개 + 61초에 100개)
Sliding Window Log
각 요청의 타임스탬프 기록
윈도우 내 요청 수 계산
현재 시간: 10:05:30
윈도우: 60초
[10:04:31, 10:04:45, 10:05:10, 10:05:25]
→ 윈도우 내 4개 요청
장점: 정확함
단점: 메모리 사용 많음
Sliding Window Counter
이전 윈도우와 현재 윈도우 가중 평균
이전 윈도우 (70개) × 30% + 현재 윈도우 (50개) × 70%
= 21 + 35 = 56개
장점: 메모리 효율적, 상당히 정확
구현 예시
Redis + Token Bucket
-- rate_limit.lua
local key = KEYS[1]
local limit = tonumber(ARGV[1])
local window = tonumber(ARGV[2])
local now = tonumber(ARGV[3])
local bucket = redis.call('HMGET', key, 'tokens', 'last_update')
local tokens = tonumber(bucket[1]) or limit
local last_update = tonumber(bucket[2]) or now
-- 토큰 리필
local elapsed = now - last_update
local refill = elapsed * (limit / window)
tokens = math.min(limit, tokens + refill)
if tokens >= 1 then
tokens = tokens - 1
redis.call('HMSET', key, 'tokens', tokens, 'last_update', now)
redis.call('EXPIRE', key, window)
return {1, tokens} -- 허용, 남은 토큰
else
return {0, 0} -- 거부
end
Node.js 미들웨어
const Redis = require('ioredis');
const redis = new Redis();
const rateLimitScript = fs.readFileSync('rate_limit.lua', 'utf8');
async function rateLimit(options) {
const { key, limit, window } = options;
return async (req, res, next) => {
const identifier = req.ip; // 또는 req.user.id
const redisKey = `ratelimit:${key}:${identifier}`;
const [allowed, remaining] = await redis.eval(
rateLimitScript,
1,
redisKey,
limit,
window,
Date.now() / 1000
);
res.set('X-RateLimit-Limit', limit);
res.set('X-RateLimit-Remaining', remaining);
if (!allowed) {
res.set('Retry-After', window);
return res.status(429).json({
error: 'Too Many Requests',
retryAfter: window,
});
}
next();
};
}
// 사용
app.use('/api/', rateLimit({ key: 'api', limit: 100, window: 60 }));
app.use('/api/search', rateLimit({ key: 'search', limit: 10, window: 60 }));
Express Rate Limit
const rateLimit = require('express-rate-limit');
const RedisStore = require('rate-limit-redis');
const limiter = rateLimit({
store: new RedisStore({
client: redis,
prefix: 'rl:',
}),
windowMs: 60 * 1000, // 1분
max: 100, // 100 요청
message: { error: 'Too many requests' },
standardHeaders: true,
legacyHeaders: false,
});
app.use('/api/', limiter);
레이트 리밋 전략
계층별 제한
const limits = {
global: { limit: 10000, window: 60 }, // 전체 API
authenticated: { limit: 1000, window: 60 }, // 인증된 사용자
anonymous: { limit: 100, window: 60 }, // 익명 사용자
endpoint: { // 엔드포인트별
'/api/search': { limit: 10, window: 60 },
'/api/upload': { limit: 5, window: 60 },
},
};
사용자 티어별
const tierLimits = {
free: { limit: 100, window: 3600 }, // 시간당 100
basic: { limit: 1000, window: 3600 }, // 시간당 1000
pro: { limit: 10000, window: 3600 }, // 시간당 10000
enterprise: { limit: 100000, window: 3600 },
};
function getRateLimit(user) {
return tierLimits[user.tier] || tierLimits.free;
}
동적 제한
// 부하에 따른 동적 조정
async function getDynamicLimit() {
const load = await getSystemLoad();
if (load > 0.9) return { limit: 50, window: 60 }; // 높은 부하
if (load > 0.7) return { limit: 75, window: 60 }; // 중간 부하
return { limit: 100, window: 60 }; // 정상
}
응답 헤더
표준 헤더
X-RateLimit-Limit: 100 # 최대 요청 수
X-RateLimit-Remaining: 45 # 남은 요청 수
X-RateLimit-Reset: 1640000000 # 리셋 시간 (Unix timestamp)
Retry-After: 30 # 재시도까지 초 (429 응답 시)
응답 예시
// 429 Too Many Requests
{
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded. Try again in 30 seconds.",
"retryAfter": 30,
"limit": 100,
"remaining": 0,
"reset": 1640000000
}
}
분산 환경
Redis Cluster
// 모든 인스턴스가 같은 Redis 참조
const redis = new Redis.Cluster([
{ host: 'redis-1', port: 6379 },
{ host: 'redis-2', port: 6379 },
{ host: 'redis-3', port: 6379 },
]);
일관성 고려
Strong Consistency: 모든 노드가 동일한 카운트 (느림)
Eventual Consistency: 일시적 불일치 허용 (빠름)
대부분의 레이트 리밋은 Eventual Consistency로 충분
약간의 초과 허용이 성능보다 덜 중요
체크리스트
설계
- [ ] 알고리즘 선택
- [ ] 제한 수치 결정
- [ ] 키 식별자 정의 (IP, 사용자, API 키)
- [ ] 티어별 제한 설계
구현
- [ ] 분산 저장소 (Redis)
- [ ] 응답 헤더 설정
- [ ] 에러 응답 형식
- [ ] 바이패스 규칙 (내부, 헬스체크)
운영
- [ ] 모니터링/알림
- [ ] 제한 초과 로깅
- [ ] 동적 조정 메커니즘
출력 형식
## Rate Limit Design
### Strategy
- 알고리즘: Token Bucket
- 저장소: Redis
### Limits
| 대상 | 제한 | 윈도우 | 키 |
|------|------|--------|-----|
| Global | 10000 | 분 | IP |
| Auth User | 1000 | 분 | user_id |
| Search API | 10 | 분 | user_id |
### Implementation
```javascript
// 핵심 구현 코드
Response Format
// 429 응답 예시
---
요청에 맞는 레이트 리밋 전략을 설계하세요.
Next.js App Router Expert
Development
A skill that turns Claude into a Next.js App Router expert.
README Generator
Development
Creates professional and comprehensive README.md files for your projects.
API Documentation Writer
Development
Generates comprehensive API documentation in OpenAPI/Swagger format.