Skip to content

feat: implement configurable rate limiting with per-endpoint and per-user limits#2

Merged
Sundriveauto merged 1 commit into
mainfrom
feat/rate-limiting
Jun 2, 2026
Merged

feat: implement configurable rate limiting with per-endpoint and per-user limits#2
Sundriveauto merged 1 commit into
mainfrom
feat/rate-limiting

Conversation

@Sundriveauto
Copy link
Copy Markdown
Owner

Summary

Replaces the previous basic rate limiting (fixed-window express-rate-limit + hardcoded sliding window) with a comprehensive, configurable, multi-tier rate limiting system that protects against abuse and DoS attacks.

Changes

New file: backend/src/config/rateLimit.config.ts

  • Centralized rate limit profile definitions per endpoint
  • Endpoint-specific rules with priority-based matching:
    • auth/login (POST): 5 req/s burst, 20 req/min sustained
    • auth/register (POST): 3 req/s burst, 10 req/min sustained
    • /certificates, /enrollments, /courses: 120 req/s burst, 1000 req/min
    • /security: 10 req/s burst, 60 req/min
    • /generator: 5 req/s burst, 30 req/min
    • /contracts: 15 req/s burst, 100 req/min
  • Role-based fallback profiles: unauthenticated (20/200), authenticated (80/600), admin (200/2000)
  • Env-var override support via setRateLimitEnvOverrides()

Rewritten: backend/src/middleware/rateLimiter.ts

  • Dual-tier rate limiting: burst (short window) + sustained (long window) checked together
  • Per-user tracking: authenticated requests keyed by userId for accurate quota enforcement
  • Per-IP tracking: anonymous requests keyed by IP address
  • Standard RateLimit headers: RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset
  • Detailed debug headers: X-RateLimit-Burst-*, X-RateLimit-Sustained-*
  • Fail-open: if Redis is unavailable, requests proceed with a warning log
  • Test mode bypass: skips rate limiting in NODE_ENV=test
  • Abuse logging: WARN-level logs when limits are exceeded (user/IP, endpoint, remaining quota)
  • Preserved legacy slidingWindowRateLimiter factory for route-specific overrides

Modified: backend/src/index.ts

  • Replaced express-rate-limit + old apiRateLimiter with new rateLimiter middleware
  • Rate limiting is conditionally applied via config.rateLimiting.enabled
  • Wires env-var overrides for login/register limits

Modified: backend/src/config/env.config.ts

  • Added rateLimiting config section with env-var-backed settings

Modified: backend/.env.example

  • Added all RATE_LIMIT_* environment variables with documentation

Configuration via environment variables

Variable Default Description
RATE_LIMIT_ENABLED true Toggle rate limiting
RATE_LIMIT_BURST_MAX 20 Default burst limit (unauth)
RATE_LIMIT_SUSTAINED_MAX 200 Default sustained limit (unauth)
RATE_LIMIT_AUTH_BURST_MAX 80 Burst limit for authenticated users
RATE_LIMIT_AUTH_SUSTAINED_MAX 600 Sustained limit for authenticated users
RATE_LIMIT_ADMIN_BURST_MAX 200 Burst limit for admin users
RATE_LIMIT_ADMIN_SUSTAINED_MAX 2000 Sustained limit for admin users
RATE_LIMIT_LOGIN_BURST_MAX 5 Login endpoint burst limit
RATE_LIMIT_REGISTER_BURST_MAX 3 Registration endpoint burst limit

Testing

  • Rate limiting applied globally with per-endpoint override rules
  • Authenticated users tracked by userId, anonymous by IP
  • Both burst and sustained limits must be satisfied
  • Fail-open when Redis is unavailable
  • Skipped entirely in test environment

…user limits

- Created centralized rate limit config (rateLimit.config.ts) with endpoint profiles
- Rewrote rate limiter middleware with dual-tier burst + sustained windows
- Per-user tracking for authenticated requests, per-IP for anonymous
- Per-endpoint overrides for auth, login, register, security, generator, export, contracts
- Env-var configurability via RATE_LIMIT_* environment variables
- Preserved legacy slidingWindowRateLimiter factory for route-specific usage
- Replaced express-rate-limit with config-driven in-house solution
@Sundriveauto Sundriveauto merged commit 2ebc8a9 into main Jun 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant