A clean, production-style rate limiting system built with Node.js, Express, and TypeScript.
Implements fixed-window and token-bucket algorithms with a pluggable store design, currently featuring an in-memory store (v1). Future releases will introduce Redis for distributed multi-instance scaling.
This project demonstrates:
-
Practical implementation of real-world rate limiting algorithms
-
Clean separation of concerns:
-
core algorithm logic
-
persistence layer
-
HTTP integration
-
-
Readable TypeScript abstractions using interfaces & composition
-
A portfolio-level example of Express middleware design
flowchart LR
C[Client] -->|HTTP| E[Express App]
E --> M[Rate Limiter Middleware]
M --> RL[RateLimiter Core]
RL --> S[(RateLimitStore)]
S --> MEM[MemoryStore]
| Component | Purpose |
|---|---|
| Client | Issues requests (Browser / Postman / curl / load test) |
| Express App | API server |
| Middleware | Inspects request, determines policy, enforces limits |
| RateLimiter Core | Implements fixed-window & token-bucket logic |
| RateLimitStore | Abstract persistence interface |
| MemoryStore | In-memory implementation of RateLimitStore |
rate-limiter/
├─ src/
│ ├─ config/ # rate-limit rules based on route/key
│ │ └─ rateLimits.ts
│ ├─ lib/ # core algorithm & storage abstractions
│ │ ├─ types.ts
│ │ ├─ store.ts
│ │ ├─ memoryStore.ts
│ │ └─ rateLimiter.ts
│ ├─ middleware/ # Express middleware wrapper
│ │ └─ rateLimiterMiddleware.ts
│ └─ server/ # Express app setup
│ └─ app.ts
├─ package.json
├─ tsconfig.json
├─ README.md
└─ LICENSE
- Node.js (TypeScript)
- Express
- ts-node-dev (development)
- (Planned) Redis for distributed store
git clone https://github.com/anubhav217/distributed-rate-limiter.git
cd distributed-rate-limiternpm installnpm run devYou should see:
Rate-limited API listening on http://localhost:3000
| Method | Path | Description | Example limit (v1) |
|---|---|---|---|
| GET | / |
Welcome message | — |
| GET | /health |
Health check | — |
| GET | /login |
Example login endpoint | Fixed window — 5 req/min |
| GET | /api/data |
Example data endpoint | Token bucket — 100 req/min |
curl.exe -i http://localhost:3000/healthcurl.exe -i http://localhost:3000/api/dataHTTP/1.1 429 Too Many Requests
{"error":"too_many_requests","message":"Rate limit exceeded. Please try again later."}
Located in src/config/rateLimits.ts:
if (req.path.startsWith('/login')) {
return {
algorithm: 'fixed-window',
rule: { maxRequests: 5, windowMs: 60_000 }
};
}
return {
algorithm: 'token-bucket',
rule: { maxRequests: 100, windowMs: 60_000, bucketCapacity: 100 }
};incrementWindowCounter(key, windowMs)consumeToken(key, capacity, refillRatePerSec)
Simple in-memory implementation for development / single-instance setups.
Implements:
- fixed-window logic
- token-bucket logic
Extracts client key (x-api-key if present, else IP)
- Jest + ts-jest
- Unit tests
- Edge case testing for both algorithms
- Integration with supertest
- Implement RedisStore for distributed rate limiting
- Add docker-compose (API + Redis)
- Add Jest tests (unit + integration)
- Per-API-key / per-plan limits
- Optional usage dashboard (React)
- Publish core rate-limiter as an npm package
/node_modules
/dist
.env
.DS_Store
*.log
MIT License — see LICENSE.
Anubhav Majumdar
- GitHub: https://github.com/anubhav217
- LinkedIn: https://www.linkedin.com/in/anubhav-majumdar/