You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The basic rate limiting middleware implemented in Issue #6 applies a single, global limit to all requests. As the platform scales with different user tiers (free, premium, admin) and API key tiers (Issue #20), a more sophisticated rate limiting system is needed that applies different limits based on user role or authentication type.
This issue enhances the rate limiting system to support multiple tiers:
Free Tier: 60 requests per minute (approx 1 req/s). Applied to unauthenticated requests and users with free role. Includes basic endpoints only (system health, meter reads). Does NOT include admin endpoints or data exports.
Premium Tier: 600 requests per minute (approx 10 req/s). Applied to users with premium role or API keys with standard or premium tier. Includes all non-admin endpoints.
Admin Tier: 6000 requests per minute (approx 100 req/s). Applied to users with admin role. Includes all endpoints including admin. Monitoring/job endpoints have separate higher limits.
Internal Tier: Unlimited (or effectively very high, 60000/min). Applied to internal services (webhook callbacks, event listener sync) that communicate via a service-to-service API key or internal network.
The rate limiter should: identify the tier based on req.user.role (from JWT auth, Issue #5) or req.apiKey.tier (from API key auth, Issue #20) or fall back to free for unauthenticated requests; apply separate rate limit counters per tier (using Redis for distributed rate limiting, Issue #12); return appropriate Retry-After headers; log rate limit violations with user identity for abuse monitoring; and provide a rate limit status endpoint (GET /api/system/rate-limits) for users to check their current usage and limits.
Architecture: Update src/middleware/rateLimiter.js to accept tier configuration. Store tier definitions in src/config/rateLimits.js. Use Redis-backed counters for production, in-memory Map for development.
Impact: Essential for fair resource allocation, abuse prevention, and monetization (free vs premium tiers). Proper rate limiting prevents a single user from degrading API performance for others.
Create Tier Detection Function: Write determineTier(req) that checks req.apiKey?.tier first (API key auth), then req.user?.role (JWT auth), else returns 'free'. Consider allowing admin role to override API key tier.
Implement Redis-Backed Store: Create a Redis store adapter for rate limit counters. Use Redis.INCR and set TTL on first request in the window. For distributed environments, this ensures accurate counts across multiple API instances.
Create Rate Limit Status Endpoint: Write GET /api/system/rate-limits returning { tier, limit, remaining, resetTime, retryAfter }. Protected by authentication. This allows clients to proactively manage their request rate.
Write Tests: Create tests/unit/rateLimiter.test.js testing tier detection, counter increments, limit enforcement. Create tests/integration/rateLimiter.test.js testing full flow: authenticate as different roles, exceed limits, check Retry-After headers, verify rate limit status endpoint.
Verification & Testing Steps
Call an API endpoint without authentication 61 times in one minute — verify the 61st request returns 429 with Retry-After header.
Authenticate as a premium user and make 601 requests in one minute — verify the 601st returns 429. Verify that free tier limit (60) does not apply to premium users.
Call GET /api/system/rate-limits with a valid JWT — verify the response shows the correct tier (premium), remaining count, and reset time.
As an admin, make requests rapidly — verify the admin limit (6000/min) applies, which is much higher than free/premium.
As an internal service with a service-to-service API key, make requests — verify no rate limiting is applied (or very high limit).
Check the application logs for rate limit violation entries — verify they include user ID/IP and tier information for abuse monitoring.
Description
The basic rate limiting middleware implemented in Issue #6 applies a single, global limit to all requests. As the platform scales with different user tiers (free, premium, admin) and API key tiers (Issue #20), a more sophisticated rate limiting system is needed that applies different limits based on user role or authentication type.
This issue enhances the rate limiting system to support multiple tiers:
Free Tier: 60 requests per minute (approx 1 req/s). Applied to unauthenticated requests and users with
freerole. Includes basic endpoints only (system health, meter reads). Does NOT include admin endpoints or data exports.Premium Tier: 600 requests per minute (approx 10 req/s). Applied to users with
premiumrole or API keys withstandardorpremiumtier. Includes all non-admin endpoints.Admin Tier: 6000 requests per minute (approx 100 req/s). Applied to users with
adminrole. Includes all endpoints including admin. Monitoring/job endpoints have separate higher limits.Internal Tier: Unlimited (or effectively very high, 60000/min). Applied to internal services (webhook callbacks, event listener sync) that communicate via a service-to-service API key or internal network.
The rate limiter should: identify the tier based on
req.user.role(from JWT auth, Issue #5) orreq.apiKey.tier(from API key auth, Issue #20) or fall back tofreefor unauthenticated requests; apply separate rate limit counters per tier (using Redis for distributed rate limiting, Issue #12); return appropriateRetry-Afterheaders; log rate limit violations with user identity for abuse monitoring; and provide a rate limit status endpoint (GET /api/system/rate-limits) for users to check their current usage and limits.Technical Context & Impact
express-rate-limitwith custom key generator and skip function, or implement custom rate limiting logic using RedisINCRwith TTL.src/middleware/rateLimiter.jsto accept tier configuration. Store tier definitions insrc/config/rateLimits.js. Use Redis-backed counters for production, in-memory Map for development.Step-by-Step Implementation Guide
src/config/rateLimits.jsexporting tier definitions:{ free: { windowMs: 60000, max: 60 }, premium: { windowMs: 60000, max: 600 }, admin: { windowMs: 60000, max: 6000 }, internal: { windowMs: 60000, max: 60000 } }. Include separate limits for write-heavy endpoints if needed.determineTier(req)that checksreq.apiKey?.tierfirst (API key auth), thenreq.user?.role(JWT auth), else returns'free'. Consider allowing admin role to override API key tier.express-rate-limitwith a customkeyGeneratorthat includes tier, user ID/IP, and endpoint group. Use a customskipfunction to exempt internal services. Store counters in Redis (fallback to memory store).Redis.INCRand set TTL on first request in the window. For distributed environments, this ensures accurate counts across multiple API instances.GET /api/system/rate-limitsreturning{ tier, limit, remaining, resetTime, retryAfter }. Protected by authentication. This allows clients to proactively manage their request rate.rateLimit({ tier: 'premium', max: 60 }).tests/unit/rateLimiter.test.jstesting tier detection, counter increments, limit enforcement. Createtests/integration/rateLimiter.test.jstesting full flow: authenticate as different roles, exceed limits, check Retry-After headers, verify rate limit status endpoint.Verification & Testing Steps
Retry-Afterheader.GET /api/system/rate-limitswith a valid JWT — verify the response shows the correct tier (premium), remaining count, and reset time.