fix(ratelimits): enterprise and team checks should be pooled limit#1255
fix(ratelimits): enterprise and team checks should be pooled limit#1255icecrasher321 merged 4 commits intostagingfrom
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Greptile Summary
This PR implements organization-aware rate limiting for team and enterprise subscription plans, fixing a critical bug where users in these plans were getting individual rate limits instead of shared organization-level limits. The changes affect five core files in the API layer and rate limiting service.
The core issue was that team and enterprise users were being rate limited individually, meaning each user in an organization had their own separate rate limit pool. For example, if an enterprise plan had a 1000 requests/minute limit, each team member would effectively get their own 1000 requests, multiplying the organization's actual capacity by the number of users.
The solution introduces organization-aware rate limiting by:
- Replacing direct subscription queries with calls to
getHighestPrioritySubscription()which properly resolves both personal and organizational subscriptions - Switching to new subscription-aware methods like
checkRateLimitWithSubscription()andgetRateLimitStatusWithSubscription()that accept the full subscription object - Using organization ID as the rate limit key for team/enterprise plans through the subscription's
referenceId, while maintaining individual user-based limits for free/pro plans
The implementation spans multiple API endpoints including workflow execution (/workflows/[id]/execute), webhook triggers (/webhooks/trigger/[path]), scheduled executions (/schedules/execute), and rate limit status checks (/users/me/rate-limit). The RateLimiter service was enhanced with a new getRateLimitKey() method that determines whether to use the user ID or organization ID based on the subscription plan, and new subscription-aware public methods while maintaining backward compatibility through deprecated legacy methods.
This change ensures that organizations can effectively control their API usage as a whole, with all team members sharing the same rate limit pool identified by the organization's reference ID, which is the expected behavior for team-based subscription tiers.
Confidence score: 4/5
- This PR addresses a well-defined business logic issue with clear implementation patterns across multiple files
- The backward compatibility approach with deprecated methods ensures existing code continues to work during transition
- Pay close attention to the RateLimiter service changes and verify the organization ID resolution logic works correctly
5 files reviewed, 3 comments
| .where(eq(subscription.referenceId, authenticatedUserId)) | ||
| .limit(1) | ||
| // Get user subscription (checks both personal and org subscriptions) | ||
| const { getHighestPrioritySubscription } = await import('@/lib/billing/core/subscription') |
There was a problem hiding this comment.
style: Using dynamic import here adds unnecessary overhead on every request. Consider importing this function at module level since it's always needed.
…imstudioai#1255) * fix(ratelimits): enterprise and team checks should be pooled limit" * fix * fix dynamic imports * fix tests" ;
Summary
Ratelimits must be pooled by org/team.
Type of Change
Testing
Manually
Checklist