@@ -4,6 +4,8 @@ import { env } from "../../shared/utils/env";
44import { redis } from "../../shared/utils/redis/redis" ;
55import { createCustomError } from "./error" ;
66import { OPENAPI_ROUTES } from "./open-api" ;
7+ import { getTransactionCredentials } from "../../shared/lib/transaction/transaction-credentials" ;
8+ import { toClientId } from "../../shared/utils/sdk" ;
79
810const SKIP_RATELIMIT_PATHS = [ "/" , ...OPENAPI_ROUTES ] ;
911
@@ -13,10 +15,11 @@ export function withRateLimit(server: FastifyInstance) {
1315 return ;
1416 }
1517
16- const epochTimeInMinutes = Math . floor ( new Date ( ) . getTime ( ) / ( 1000 * 60 ) ) ;
17- const key = `rate-limit:global:${ epochTimeInMinutes } ` ;
18- const count = await redis . incr ( key ) ;
19- redis . expire ( key , 2 * 60 ) ;
18+ const epochMinutes = Math . floor ( new Date ( ) . getTime ( ) / ( 1000 * 60 ) ) ;
19+
20+ const globalRateLimitKey = `rate-limit:global:${ epochMinutes } ` ;
21+ const count = await redis . incr ( globalRateLimitKey ) ;
22+ redis . expire ( globalRateLimitKey , 2 * 60 ) ;
2023
2124 if ( count > env . GLOBAL_RATE_LIMIT_PER_MIN ) {
2225 throw createCustomError (
@@ -25,5 +28,21 @@ export function withRateLimit(server: FastifyInstance) {
2528 "TOO_MANY_REQUESTS" ,
2629 ) ;
2730 }
31+
32+ // Lite mode enforces a rate limit per team.
33+ if ( env . ENGINE_MODE === "lite" ) {
34+ const { clientId } = getTransactionCredentials ( request ) ;
35+ const clientRateLimitKey = `rate-limit:client-id:${ clientId } ` ;
36+ const count = await redis . incr ( clientRateLimitKey ) ;
37+ redis . expire ( globalRateLimitKey , 2 * 60 ) ;
38+
39+ if ( count > env . LITE_CLIENT_RATE_LIMIT_PER_MIN ) {
40+ throw createCustomError (
41+ `${ env . LITE_CLIENT_RATE_LIMIT_PER_MIN } requests/minute rate limit exceeded. Upgrade to Engine Standard to get a dedicated Engine without rate limits.` ,
42+ StatusCodes . TOO_MANY_REQUESTS ,
43+ "TOO_MANY_REQUESTS" ,
44+ ) ;
45+ }
46+ }
2847 } ) ;
2948}
0 commit comments