@prakarsh123/rate-limiter
v1.0.0
Published
Production-ready API Rate Limiting & Quota Management - Use as a library or standalone service
Downloads
9
Maintainers
Readme
Rate Limiter Service
Production-ready API Rate Limiting & Quota Management Service built with Node.js/TypeScript, Fastify, and Redis.
🚀 Features
Multiple Rate Limiting Algorithms
- Token Bucket (smooth rate limiting with burst capacity)
- Fixed Window (simple time-based limiting)
- Sliding Window (accurate, prevents boundary issues)
Dual Interface Support
- REST API (Fastify)
- gRPC (coming soon)
Distributed & Scalable
- Redis-backed distributed state
- Works across multiple service instances
- Atomic operations via Lua scripts
Granular Control
- Per-user rate limiting
- Per-API-endpoint limiting
- Per-IP limiting
- Composite keys (user+endpoint, IP+endpoint)
Smart Notifications
- Webhook alerts at configurable thresholds
- Retry logic with exponential backoff
- HMAC signatures for security
Production Ready
- Docker deployment
- TypeScript client SDK
- OpenAPI/Swagger documentation
- Health checks and monitoring
📦 Quick Start
Using Docker Compose (Recommended)
# Clone the repository
git clone <repo-url>
cd rate-limiter-service
# Start the service
docker-compose -f docker/docker-compose.yml up -d
# Check health
curl http://localhost:3000/v1/healthLocal Development
# Install dependencies
npm install
# Copy environment file
cp .env.example .env
# Start Redis (required)
docker run -d -p 6379:6379 redis:7-alpine
# Run in development mode
npm run dev
# Or build and run
npm run build
npm start📖 API Documentation
Once the service is running, visit:
- Swagger UI: http://localhost:3000/docs
- API Base: http://localhost:3000
🔧 Usage Examples
Basic Rate Limiting
import { RateLimiterClient } from "./client/rest-client";
const client = new RateLimiterClient("http://localhost:3000");
// Check rate limit
const result = await client.check({
key: "user:123",
endpoint: "/api/users",
algorithm: "token_bucket",
limit: 100,
window: 3600, // 1 hour in seconds
});
if (result.allowed) {
console.log("Request allowed!");
console.log(`Remaining: ${result.remaining}/${result.limit}`);
} else {
console.log(`Rate limited! Retry after ${result.retryAfter}s`);
}Using Rules
// Create a reusable rule
const rule = await client.createRule({
name: "API Users Endpoint",
algorithm: "token_bucket",
limit: 1000,
window: 3600,
keys: [{ type: "user", value: "*" }],
webhookUrl: "https://example.com/webhooks/rate-limit",
thresholds: [80, 90, 100],
});
// Use the rule
const result = await client.check({
key: "user:456",
ruleId: rule.id,
});Express Middleware
import express from "express";
import { RateLimiterClient } from "./client/rest-client";
const app = express();
const rateLimiter = new RateLimiterClient("http://localhost:3000");
app.use(async (req, res, next) => {
try {
const result = await rateLimiter.check({
key: `user:${req.user?.id || req.ip}`,
endpoint: req.path,
algorithm: "token_bucket",
limit: 100,
window: 3600,
});
res.set("X-RateLimit-Limit", result.limit);
res.set("X-RateLimit-Remaining", result.remaining);
res.set("X-RateLimit-Reset", result.resetAt);
if (!result.allowed) {
return res.status(429).json({
error: "Too many requests",
retryAfter: result.retryAfter,
});
}
next();
} catch (error) {
next(); // Fail open on errors
}
});🎯 Algorithm Comparison
| Algorithm | Pros | Cons | Best For | | ------------------ | --------------------------------------------- | ------------------------------------ | ------------------------------------- | | Token Bucket | Smooth rate limiting, allows bursts, flexible | More complex, slightly higher memory | APIs with variable load, file uploads | | Fixed Window | Simple, fast, low memory | Boundary issues, can be gamed | High throughput, simple limits | | Sliding Window | Most accurate, no boundary issues | Higher memory, more complex | Critical operations, fraud prevention |
🔄 Switching Algorithms
Algorithms can be switched at multiple levels:
1. Per-Rule Configuration
await client.createRule({
algorithm: "token_bucket", // or 'fixed_window', 'sliding_window'
// ...
});2. Runtime Selection
await client.check({
key: "user:123",
algorithm: "sliding_window", // Override per request
limit: 100,
window: 3600,
});3. Dynamic Based on User Tier
const algorithm = tier === "free" ? "fixed_window" : "token_bucket";
await client.check({ key, algorithm, limit, window });🔔 Webhook Notifications
Configure webhooks to receive notifications when rate limits are approached:
await client.createRule({
name: "Payment API",
algorithm: "sliding_window",
limit: 100,
window: 3600,
webhookUrl: "https://your-app.com/webhooks/rate-limit",
thresholds: [80, 90, 100], // Notify at 80%, 90%, 100%
});Webhook payload:
{
"key": "user:123",
"endpoint": "/api/payment",
"limit": 100,
"currentUsage": 85,
"threshold": 80,
"timestamp": "2026-01-11T02:30:00Z",
"message": "Rate limit 80% threshold reached for user:123"
}🏗️ Architecture
┌─────────────────────────────────────────────────┐
│ Your Application │
│ ┌──────────┐ ┌──────────┐ │
│ │ API GW 1 │ │ API GW 2 │ │
│ └────┬─────┘ └────┬─────┘ │
│ │ │ │
│ └────────┬────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────────────┐ │
│ │ Rate Limiter Service │◄──── REST/gRPC │
│ │ (This Service) │ │
│ └───────────┬───────────┘ │
│ │ │
│ ▼ │
│ ┌──────────┐ │
│ │ Redis │ (Distributed State) │
│ └──────────┘ │
└─────────────────────────────────────────────────┘🛠️ Configuration
Environment variables (.env):
# Server
NODE_ENV=development
REST_PORT=3000
GRPC_PORT=50051
# Redis
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_PASSWORD=
REDIS_DB=0
# Webhooks
WEBHOOK_TIMEOUT=5000
WEBHOOK_MAX_RETRIES=3
WEBHOOK_RETRY_DELAY=1000
# Logging
LOG_LEVEL=info📊 Monitoring
Health Check
curl http://localhost:3000/v1/healthService Info
curl http://localhost:3000/v1/info🧪 Testing
# Run all tests
npm test
# Run integration tests
npm run test:integration
# Watch mode
npm run test:watch📝 API Endpoints
Rate Limiting
POST /v1/check- Check if request is allowed
Rule Management
POST /v1/rules- Create ruleGET /v1/rules- List all rulesGET /v1/rules/:id- Get rule by IDPUT /v1/rules/:id- Update ruleDELETE /v1/rules/:id- Delete rule
Health
GET /v1/health- Health checkGET /v1/info- Service information
🚢 Deployment
Docker
docker build -f docker/Dockerfile -t rate-limiter .
docker run -p 3000:3000 -e REDIS_HOST=redis rate-limiterDocker Compose
docker-compose -f docker/docker-compose.yml up -dKubernetes (coming soon)
📄 License
MIT
🤝 Contributing
Contributions welcome! Please read our contributing guidelines.
💬 Support
- Documentation: http://localhost:3000/docs
- Issues: GitHub Issues
- Email: [email protected]
