web / lib/services/rate-limit-service
lib/services/rate-limit-service
Provides a service for rate-limiting requests.
This service implements a flexible, in-memory rate-limiting mechanism to protect endpoints from abuse. It tracks requests from different identifiers (like IP addresses or session IDs) and enforces limits based on a specified number of requests within a given time window.
Rate Limiting vs Quotas
This service works alongside QuotaService but serves a different purpose:
RateLimitService (this service):
- Purpose: Short-term abuse prevention (DDoS, spam, burst attacks)
- Storage: In-memory (fast, ephemeral)
- Scope: Per IP address or identifier
- Time windows: Seconds to hours
- Reset: Sliding windows
QuotaService:
- Purpose: Long-term resource management (fair usage, capacity planning)
- Storage: Database (persistent, accurate)
- Scope: Per user ID
- Time windows: Hours to lifetime
- Reset: Fixed times (midnight UTC)
Both checks typically run together - rate limits first (fast fail), then quotas (accurate tracking).
Example
// Typical usage pattern: check both rate limits and quotas
import { getRateLimitService } from '@/lib/services/rate-limit-service';
import { getQuotaService } from '@/lib/services/quota-service';
// 1. Rate limit check (fast, prevents abuse)
const rateLimitService = getRateLimitService(payload);
const rateCheck = rateLimitService.checkTrustLevelRateLimit(
clientIp,
user,
"FILE_UPLOAD"
);
if (!rateCheck.allowed) {
return res.status(429).json({ error: "Too many requests" });
}
// 2. Quota check (accurate, tracks long-term usage)
const quotaService = getQuotaService(payload);
const quotaCheck = await quotaService.checkQuota(
user,
QUOTA_TYPES.FILE_UPLOADS_PER_DAY
);
if (!quotaCheck.allowed) {
throw new QuotaExceededError(...);
}
// 3. Process the request
await processFileUpload();Key features include:
- Multi-window rate limiting (burst, hourly, daily)
- Trust-level-aware rate limits
- Checking if a request is allowed
- Blocking identifiers that exceed the limit
- Providing standard rate-limit headers for HTTP responses
- Automatic cleanup of expired entries
See
- QuotaService for long-term resource management
- Rate Limiting Documentation
- Quotas Documentation
Classes
RateLimitService
Constructors
Constructor
new RateLimitService(
payload):RateLimitService
Parameters
payload
BasePayload
Returns
Methods
destroy()
destroy():
void
Cleanup method to clear interval and cache.
Returns
void
checkRateLimit()
checkRateLimit(
identifier,limit,windowMs):object
Check if a request should be rate limited.
Parameters
identifier
string
IP address or session ID.
limit
number = 10
Maximum requests allowed
windowMs
number = ...
Time window in milliseconds
Returns
object
Object containing rate limit status
allowed
allowed:
boolean
remaining
remaining:
number
resetTime
resetTime:
number
blocked
blocked:
boolean
checkMultiWindowRateLimit()
checkMultiWindowRateLimit(
baseIdentifier,windows):MultiWindowRateLimitResult
Check multiple rate limit windows for a single identifier.
This method checks all configured windows and returns on the first failure. It’s useful for implementing complex rate limiting strategies like:
- Burst protection (e.g., 1 request per 10 seconds)
- Hourly limits (e.g., 5 requests per hour)
- Daily limits (e.g., 100 requests per day).
Parameters
baseIdentifier
string
Base identifier for the request (e.g., “webhook:token123”).
windows
Array of rate limit windows to check.
readonly RateLimitWindow[] | RateLimitWindow[]
Returns
Result indicating if request is allowed and which window failed (if any).
checkConfiguredRateLimit()
checkConfiguredRateLimit(
baseIdentifier,config):MultiWindowRateLimitResult
Check rate limits using a configuration object.
Parameters
baseIdentifier
string
Base identifier for the request.
config
Rate limit configuration with windows.
Returns
Result indicating if request is allowed.
getRateLimitStatus()
getRateLimitStatus(
identifier):null| {count:number;resetTime:number;blocked:boolean; }
Get current rate limit status without incrementing.
Parameters
identifier
string
Returns
null | { count: number; resetTime: number; blocked: boolean; }
resetRateLimit()
resetRateLimit(
identifier):void
Reset rate limit for an identifier.
Parameters
identifier
string
Returns
void
blockIdentifier()
blockIdentifier(
identifier,durationMs):void
Block an identifier immediately.
Parameters
identifier
string
durationMs
number = ...
Returns
void
getRateLimitHeaders()
getRateLimitHeaders(
identifier,limit):Record<string,string>
Get rate limit headers for HTTP responses.
Parameters
identifier
string
limit
number
Returns
Record<string, string>
getStatistics()
getStatistics():
object
Get statistics about current rate limits.
Returns
object
totalEntries
totalEntries:
number
blockedEntries
blockedEntries:
number
activeEntries
activeEntries:
number
getRateLimitsByTrustLevel()
getRateLimitsByTrustLevel(
user,endpointType):RateLimitConfig
Get rate limit configuration based on user trust level.
Parameters
user
The user object containing trust level
undefined | null | User
endpointType
The type of endpoint (FILE_UPLOAD, API_GENERAL, etc.)
"FILE_UPLOAD" | "API_GENERAL"
Returns
Rate limit configuration for the user’s trust level
checkTrustLevelRateLimit()
checkTrustLevelRateLimit(
identifier,user,endpointType):MultiWindowRateLimitResult
Check rate limits with trust level awareness.
Parameters
identifier
string
IP address or session ID
user
User object to determine trust level
undefined | null | User
endpointType
The type of endpoint
"FILE_UPLOAD" | "API_GENERAL"
Returns
Multi-window rate limit result
Interfaces
RateLimitWindow
Configuration for a single rate limit window.
Properties
limit
limit:
number
Maximum number of requests allowed in this window
windowMs
windowMs:
number
Time window in milliseconds
name?
optionalname:string
Optional name for this window (e.g., “burst”, “hourly”, “daily”)
MultiWindowRateLimitResult
Result from checking multiple rate limit windows.
Properties
allowed
allowed:
boolean
Whether the request is allowed (passes all windows)
failedWindow?
optionalfailedWindow:string
Name of the window that failed (if any)
resetTime?
optionalresetTime:number
Time when the failed window resets
remaining?
optionalremaining:number
Remaining requests in the most restrictive window
details?
optionaldetails:object
Details of the check that failed
limit
limit:
number
windowMs
windowMs:
number
remaining
remaining:
number
resetTime
resetTime:
number
RateLimitConfig
Configuration for multi-window rate limiting.
Properties
windows
windows: readonly
RateLimitWindow[] |RateLimitWindow[]
Variables
RATE_LIMITS
constRATE_LIMITS:object
Type declaration
FILE_UPLOAD
readonlyFILE_UPLOAD:object
FILE_UPLOAD.windows
readonlywindows: readonly [{limit:1;windowMs:number;name:"burst"; }, {limit:5;windowMs:number;name:"hourly"; }, {limit:20;windowMs:number;name:"daily"; }]
PROGRESS_CHECK
readonlyPROGRESS_CHECK:object
PROGRESS_CHECK.windows
readonlywindows: readonly [{limit:10;windowMs:1000;name:"burst"; }, {limit:100;windowMs:number;name:"hourly"; }]
IMPORT_RETRY
readonlyIMPORT_RETRY:object
IMPORT_RETRY.windows
readonlywindows: readonly [{limit:1;windowMs:number;name:"burst"; }, {limit:10;windowMs:number;name:"hourly"; }, {limit:50;windowMs:number;name:"daily"; }]
ADMIN_IMPORT_RESET
readonlyADMIN_IMPORT_RESET:object
ADMIN_IMPORT_RESET.windows
readonlywindows: readonly [{limit:5;windowMs:number;name:"burst"; }, {limit:50;windowMs:number;name:"hourly"; }]
RETRY_RECOMMENDATIONS
readonlyRETRY_RECOMMENDATIONS:object
RETRY_RECOMMENDATIONS.windows
readonlywindows: readonly [{limit:10;windowMs:number;name:"burst"; }, {limit:100;windowMs:number;name:"hourly"; }]
API_GENERAL
readonlyAPI_GENERAL:object
API_GENERAL.windows
readonlywindows: readonly [{limit:5;windowMs:1000;name:"burst"; }, {limit:50;windowMs:number;name:"hourly"; }]
WEBHOOK_TRIGGER
readonlyWEBHOOK_TRIGGER:object
WEBHOOK_TRIGGER.windows
readonlywindows: readonly [{limit:1;windowMs:number;name:"burst"; }, {limit:5;windowMs:number;name:"hourly"; }]
NEWSLETTER_SUBSCRIBE
readonlyNEWSLETTER_SUBSCRIBE:object
NEWSLETTER_SUBSCRIBE.windows
readonlywindows: readonly [{limit:1;windowMs:number;name:"burst"; }, {limit:3;windowMs:number;name:"hourly"; }, {limit:10;windowMs:number;name:"daily"; }]
Functions
getRateLimitService()
getRateLimitService(
payload):RateLimitService
Parameters
payload
BasePayload
Returns
resetRateLimitService()
resetRateLimitService():
void
Reset the rate limit service singleton (for testing). Call this in afterEach/afterAll to ensure clean state between tests.
Returns
void
getClientIdentifier()
getClientIdentifier(
request):string
Parameters
request
Request
Returns
string