It provides atomic enforcement using Redis and auditable decisions stored in PostgreSQL.
It's designed as an externalized infrastructure service to decouple rate limiting logic from application code.
- API request throttling
- Multi-tenant quotas (daily/monthly)
- Abuse prevention and burst control
- Unified rate limiting for microservices
- Public API protection
- Daily/monthly quotas align to UTC day/month boundaries.
rate_limit_eventsis append-only for auditability.RateLimit-*headers follow RFC 9331.
| Feature | Description |
|---|---|
| Multiple algorithms | Fixed window, sliding window, token bucket, daily/monthly quotas |
| Atomic enforcement | Redis Lua scripts + MULTI for correctness under concurrency |
| Idempotency | Safe /v1/check via X-Idempotency-Key |
| Audit log | Decisions stored in rate_limit_events |
| RFC 9331 headers | RateLimit-* + Retry-After on /v1/check |
| Fail-open/closed | Redis outage strategy via FAIL_OPEN |
| Optimistic concurrency | ETag / If-Match for rule updates |
| Retention cleanup | Automated deletion of old audit events |
| Metrics | Prometheus text metrics at /metrics |
| Docker-first | One-command startup with Docker Compose |
| Component | Tech |
|---|---|
| API | NestJS 10 |
| Database | PostgreSQL 16 |
| Cache / Rate limit | Redis 7 |
| ORM | Prisma |
| Runtime | Node.js 20 |
| Deployment | Docker & Docker Compose |
Client / Service
β
POST /v1/check
β
PostgreSQL (rules + api keys)
β
Redis (atomic algorithm + counters)
β
PostgreSQL (audit events)
- Single source of truth for rules
- Atomic counters for correctness
- Lightweight API surface for easy integration
- Auditability via immutable event log
- Predictable error responses (429/401/400)
All protected endpoints require:
X-API-Key: <API_KEY>
Bootstrap key for initial setup is defined in .env:
BOOTSTRAP_API_KEY=change_me_bootstrapGET /healthβ service health check
POST /v1/checkβ rate limit decision
POST /v1/rulesβ create ruleGET /v1/rulesβ list rulesGET /v1/rules/{id}β rule details (returnsETag)PUT /v1/rules/{id}β update rule (If-Matchrequired)DELETE /v1/rules/{id}β delete rule (If-Matchrequired)
POST /v1/keysβ create keyGET /v1/keysβ list keysPOST /v1/keys/{id}/rotateβ rotate keyPOST /v1/keys/{id}/revokeβ revoke key
GET /metricsβ Prometheus text format
npm run test:unit
npm run test:e2ecurl -X POST http://localhost:3000/v1/keys \
-H "Content-Type: application/json" \
-H "X-API-Key: change_me_bootstrap" \
-d '{"name":"primary"}'curl -X POST http://localhost:3000/v1/rules \
-H "Content-Type: application/json" \
-H "X-API-Key: change_me_bootstrap" \
-d '{"name":"login","scopeType":"api_key","algorithm":"fixed_window","limit":5,"intervalMs":60000}'curl -X POST http://localhost:3000/v1/check \
-H "X-API-Key: change_me_bootstrap" \
-H "X-Idempotency-Key: test-1" \
-H "Content-Type: application/json" \
-d '{"rule":"RULE_ID"}'git clone https://github.com/cresterienvogel/node-rate-limit-service.git
cd node-rate-limit-servicecp .env.example .envdocker compose up --buildService will be available at:
http://localhost:3000
Swagger:
http://localhost:3000/docs