ソース情報
- リポジトリ
- tools-only/X-Skills
- ソースの最終更新活動
- 2026年2月9日 04:32
- 検出された SKILL.md の言語
- 英語
- スター
- 7
- フォーク
- 1
インストール方法
デフォルトでは、最初にソースを確認する Prompt が選択されています。直接コマンドに切り替えるか、ローカルコピーをダウンロードすることもできます。
ソースファイルを確認
インストールを決める前に、SKILL.md と SkillsMP に表示されている付属ファイルをお読みください。
メニュー
デフォルトでは、最初にソースを確認する Prompt が選択されています。直接コマンドに切り替えるか、ローカルコピーをダウンロードすることもできます。
インストールを決める前に、SKILL.md と SkillsMP に表示されている付属ファイルをお読みください。
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
直接コマンドでは確認用 Prompt が省略されます。実行前にソースを確認してください。
npx skills add https://github.com/tools-only/X-Skills --skill add-rate-limitingコマンドは1行のまま表示されます。コピー前に横へスクロールして全体を確認してください。
ローカルで確認しますか?SkillsMP が現在取得できるファイルをダウンロードできます。
Index of Build Systems Skills
Coordination patterns for distributed dataflow systems including barriers, epochs, and distributed snapshots
Windowing, sessionization, time-series aggregation, and late data handling for streaming systems
SOC 職業分類に基づく
SKILL.md を表示中
| name | add-rate-limiting |
| description | Add rate limiting to API endpoints |
| shortcut | rate |
Implement production-ready rate limiting with token bucket, sliding window, or fixed window algorithms using Redis for distributed state management.
Use /add-rate-limiting when you need to:
DON'T use this when:
This command implements Token Bucket algorithm with Redis as the primary approach because:
Alternative considered: Sliding Window
Alternative considered: Fixed Window
Alternative considered: Leaky Bucket
Before running this command:
Select algorithm based on requirements: Token Bucket for user-facing APIs, Sliding Window for strict compliance, Fixed Window for internal APIs.
Set up Redis client with connection pooling, retry logic, and failover handling for high availability.
Create middleware that intercepts requests, checks Redis state, and enforces limits with proper HTTP headers.
Configure different limits for user segments (anonymous, free, premium, enterprise) based on business requirements.
Instrument rate limiter with metrics for blocked requests, Redis latency, and tier usage patterns.
The command generates:
rate-limiter.js or rate_limiter.py - Core rate limiting middlewareredis-config.js - Redis connection configuration with failoverrate-limit-tiers.json - Tiered limit definitionsrate-limiter.test.js - Comprehensive test suiteREADME.md - Integration guide and configuration optionsdocker-compose.yml - Redis setup for local development// rate-limiter.js
const Redis = require('ioredis');
class TokenBucketRateLimiter {
constructor(redisClient, options = {}) {
this.redis = redisClient;
this.defaultOptions = {
points: 100, // Number of tokens
duration: 60, // Time window in seconds
blockDuration: 60, // Block duration after limit exceeded
keyPrefix: 'rl', // Redis key prefix
...options
};
}
/**
* Token bucket algorithm using Redis
* Returns: { allowed: boolean, remaining: number, resetTime: number }
*/
async consume(identifier, points = 1, options = {}) {
const opts = { ...this.defaultOptions, ...options };
const key = `${opts.keyPrefix}:${identifier}`;
const now = Date.now();
// Lua script for atomic token bucket operations
const luaScript = `
local key = KEYS[1]
local capacity = tonumber(ARGV[1])
local refill_rate = tonumber(ARGV[2])
local requested = tonumber(ARGV[3])
local now = tonumber(ARGV[4])
local ttl = tonumber(ARGV[5])
-- Get current state or initialize
local tokens = tonumber(redis.call('HGET', key, 'tokens'))
local last_refill = tonumber(redis.call('HGET', key, 'last_refill'))
if not tokens then
tokens = capacity
last_refill = now
end
-- Calculate tokens to add since last refill
local time_passed = now - last_refill
local tokens_to_add = math.floor(time_passed * refill_rate)
tokens = math.min(capacity, tokens + tokens_to_add)
last_refill = now
-- Check if we can fulfill request
if tokens >= requested then
tokens = tokens - requested
redis.call('HMSET', key, 'tokens', tokens, 'last_refill', last_refill)
redis.call('EXPIRE', key, ttl)
return {1, tokens, last_refill}
else
redis.call('HMSET', key, 'tokens', tokens, 'last_refill', last_refill)
redis.call('EXPIRE', key, ttl)
return {0, tokens, last_refill}
end
`;
refillRate = opts. / opts.;
result = ..(
luaScript,
,
key,
opts.,
refillRate,
points,
now,
opts.
);
[allowed, remaining, lastRefill] = result;
resetTime = lastRefill + (opts. * );
{
: allowed === ,
: .(remaining),
: (resetTime).(),
: allowed === ? : .((opts. * - (now - lastRefill)) / )
};
}
() {
(req, res, next) => {
{
identifier = req.?. || req.;
tier = getTier ? (req) : ;
tierConfig = .(tier);
result = .(identifier, , tierConfig);
res.({
: tierConfig.,
: result.,
: result.
});
(!result.) {
res.(, result.);
res.().({
: ,
: ,
: result.
});
}
();
} (error) {
.(, error);
();
}
};
}
() {
tiers = {
: { : , : },
: { : , : },
: { : , : },
: { : , : }
};
tiers[tier] || tiers.;
}
}
redis = ({
: process.. || ,
: process.. || ,
: .(times * , ),
:
});
rateLimiter = (redis);
app.(rateLimiter.( (req) => {
(req.?. === ) ;
(req.?. === ) ;
(req.) ;
;
}));
app.(,
rateLimiter.( ({ : , : })),
handleGenerate
);
. = ;
# rate_limiter.py
import time
import redis.asyncio as aioredis
from fastapi import Request, Response, HTTPException
from typing import Optional, Callable
import asyncio
class SlidingWindowRateLimiter:
def __init__(self, redis_client: aioredis.Redis, window_size: int = 60, max_requests: int = 100):
self.redis = redis_client
self.window_size = window_size
self.max_requests = max_requests
self.key_prefix = "rate_limit"
async def is_allowed(self, identifier: str, tier_config: dict = None) -> dict:
"""
Sliding window algorithm using Redis sorted set
Each request is a member with score = timestamp
"""
config = tier_config or {'max_requests': self.max_requests, 'window_size': self.window_size}
now = time.time()
window_start = now - config['window_size']
key = f"{self.key_prefix}:{identifier}"
# Redis pipeline for atomic operations
pipe = self.redis.pipeline()
pipe.zremrangebyscore(key, , window_start)
pipe.zcard(key)
pipe.zadd(key, {(now): now})
pipe.expire(key, config[] + )
results = pipe.execute()
request_count = results[]
request_count >= config[]:
oldest = .redis.zrange(key, , , withscores=)
oldest:
oldest_time = oldest[][]
retry_after = (config[] - (now - oldest_time)) +
:
retry_after = config[]
{
: ,
: ,
: (now + retry_after),
: retry_after
}
remaining = config[] - request_count -
reset_time = (now + config[])
{
: ,
: remaining,
: reset_time,
:
}
():
():
identifier = (request.state, , ) request.client.host
tier_config =
get_tier:
tier_config = get_tier(request)
result = .is_allowed(identifier, tier_config)
response =
result[]:
response = call_next(request)
:
response = Response(
content=,
status_code=,
media_type=
)
response.headers[] = (tier_config[] tier_config .max_requests)
response.headers[] = (result[])
response.headers[] = (result[])
result[]:
response.headers[] = (result[])
response
rate_limit_middleware
fastapi FastAPI
contextlib asynccontextmanager
():
app.state.redis = aioredis.from_url()
app.state.rate_limiter = SlidingWindowRateLimiter(app.state.redis)
app.state.redis.close()
app = FastAPI(lifespan=lifespan)
() -> :
user = (request.state, , )
user:
{: , : }
user.get() == :
{: , : }
user.get() == :
{: , : }
:
{: , : }
app.middleware()(app.state.rate_limiter.middleware(get_user_tier))
// advanced-rate-limiter.js - Multi-layer protection
const Redis = require('ioredis');
class MultiLayerRateLimiter {
constructor(redisClient) {
this.redis = redisClient;
}
/**
* Layered rate limiting strategy:
* 1. IP-based (DDoS protection)
* 2. User-based (fair usage)
* 3. Endpoint-specific (expensive operations)
*/
async checkLayers(req) {
const layers = [
// Layer 1: IP-based rate limiting (DDoS protection)
{
name: 'ip',
identifier: req.ip,
limits: { points: 1000, duration: 60 }, // 1000 req/min per IP
priority: 'high'
},
// Layer 2: User-based rate limiting
{
name: 'user',
identifier: req.user?.id || `anon:${req.ip}`,
limits: this.getUserTierLimits(req.user),
priority: 'medium'
},
// Layer 3: Endpoint-specific limiting
{
name: 'endpoint',
identifier: ,
: .(req.),
:
}
];
( layer layers) {
result = .(layer);
(!result.) {
{
: ,
: layer.,
...result
};
}
}
{ : };
}
() {
key = ;
now = .();
count = ..(key);
(count === ) {
..(key, layer..);
}
ttl = ..(key);
allowed = count <= layer..;
{
allowed,
: .(, layer.. - count),
: now + (ttl * ),
: allowed ? : ttl
};
}
() {
(!user) { : , : };
tiers = {
: { : , : },
: { : , : },
: { : , : }
};
tiers[user.] || tiers.;
}
() {
expensiveEndpoints = {
: { : , : },
: { : , : },
: { : , : }
};
expensiveEndpoints[path] || { : , : };
}
() {
(req, res, next) => {
{
result = .(req);
(result.) {
res.({
: result.,
: result.,
: result.
});
res.().({
: ,
: result.,
: result.,
:
});
}
();
} (error) {
.(, error);
();
}
};
}
}
. = ;
| Error | Cause | Solution |
|---|---|---|
| "Redis connection failed" | Redis server unreachable | Check Redis server status, verify connection string, implement connection retry |
| "Rate limiter fail-closed" | Redis timeout, middleware blocking all traffic | Implement fail-open strategy with circuit breaker pattern |
| "Inconsistent rate limits" | Clock skew across servers | Use Redis time (TIME command) instead of server time |
| "Memory exhaustion" | Too many keys, no TTL set | Always set TTL on rate limit keys, use key expiration monitoring |
| "False positives from NAT" | Multiple users behind same IP | Use authenticated user IDs when available, consider X-Forwarded-For |
Rate Limit Algorithms
Tier Definitions
{
"anonymous": { "points": 20, "duration": 60 },
"free": { "points": 100, "duration": 60 },
"premium": { "points": 1000, "duration": 60 },
"enterprise": { "points": 10000, "duration": 60 }
}
Redis Configuration
DO:
DON'T:
TIPS:
Latency Impact
Redis Memory Usage
Throughput
Rate Limits Not Enforced
# Check Redis connectivity
redis-cli -h localhost -p 6379 ping
# Verify keys are being created
redis-cli --scan --pattern 'rl:*' | head -10
# Check TTL is set correctly
redis-cli TTL rl:user:123456
Too Many False Positives
# Review blocked requests by IP
redis-cli --scan --pattern 'rl:ip:*' | xargs redis-cli MGET
# Check tier assignments
# Review application logs for tier calculation
# Analyze legitimate traffic patterns
# Adjust limits based on p95/p99 usage
Redis Memory Issues
# Check memory usage
redis-cli INFO memory
# Count rate limit keys
redis-cli --scan --pattern 'rl:*' | wc -l
# Review keys without TTL
redis-cli --scan --pattern 'rl:*' | xargs redis-cli TTL | grep -c "^-1"
/create-monitoring - Monitor rate limit metrics and violations/api-authentication-builder - Integrate with auth for user-based limits/api-load-tester - Test rate limiter under realistic load/setup-logging - Log rate limit violations for analysis