Skip to content

cresterienvogel/node-rate-limit-service

Repository files navigation

🚦 Rate Limit & Quota Service


πŸ“Œ Overview

Rate Limit & Quota Service is a backend API for centralized rate limiting and quotas.

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.


πŸ“Ž Use Cases

  • API request throttling
  • Multi-tenant quotas (daily/monthly)
  • Abuse prevention and burst control
  • Unified rate limiting for microservices
  • Public API protection

πŸ“¦ Notes

  • Daily/monthly quotas align to UTC day/month boundaries.
  • rate_limit_events is append-only for auditability.
  • RateLimit-* headers follow RFC 9331.

✨ Features

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

🧰 Tech Stack

Component Tech
API NestJS 10
Database PostgreSQL 16
Cache / Rate limit Redis 7
ORM Prisma
Runtime Node.js 20
Deployment Docker & Docker Compose

🧠 Architecture Highlights

Rate limit flow

Client / Service
  ↓
POST /v1/check
  ↓
PostgreSQL (rules + api keys)
  ↓
Redis (atomic algorithm + counters)
  ↓
PostgreSQL (audit events)

Design principles

  • 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)

πŸ” Authentication

All protected endpoints require:

X-API-Key: <API_KEY>

Bootstrap key for initial setup is defined in .env:

BOOTSTRAP_API_KEY=change_me_bootstrap

πŸ—ΊοΈ API Endpoints

Health

  • GET /health β€” service health check

Rate Limit

  • POST /v1/check β€” rate limit decision

Rules

  • POST /v1/rules β€” create rule
  • GET /v1/rules β€” list rules
  • GET /v1/rules/{id} β€” rule details (returns ETag)
  • PUT /v1/rules/{id} β€” update rule (If-Match required)
  • DELETE /v1/rules/{id} β€” delete rule (If-Match required)

API Keys

  • POST /v1/keys β€” create key
  • GET /v1/keys β€” list keys
  • POST /v1/keys/{id}/rotate β€” rotate key
  • POST /v1/keys/{id}/revoke β€” revoke key

Metrics

  • GET /metrics β€” Prometheus text format

πŸ§ͺ Jest Tests

npm run test:unit
npm run test:e2e

πŸ§ͺ Quick Tests

Create API key

curl -X POST http://localhost:3000/v1/keys \
  -H "Content-Type: application/json" \
  -H "X-API-Key: change_me_bootstrap" \
  -d '{"name":"primary"}'

Create rule

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}'

Check limit (idempotent)

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"}'

πŸš€ Quick Start

1. Clone repository

git clone https://github.com/cresterienvogel/node-rate-limit-service.git
cd node-rate-limit-service

2. Create .env

cp .env.example .env

3. Run with Docker

docker compose up --build

Service will be available at:

http://localhost:3000

Swagger:

http://localhost:3000/docs