Skip to content

Commit e1ac201

Browse files
improvement(ratelimits, sockets): increase across all plans, reconnecting notif for sockets (#3096)
* improvement(rate-limits): increase across all plans * improve sockets with reconnecting * address bugbot comment * fix typing
1 parent 6cb3977 commit e1ac201

File tree

13 files changed

+365
-256
lines changed

13 files changed

+365
-256
lines changed

apps/docs/content/docs/en/execution/api.mdx

Lines changed: 37 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,16 @@ All API responses include information about your workflow execution limits and u
2727
"limits": {
2828
"workflowExecutionRateLimit": {
2929
"sync": {
30-
"requestsPerMinute": 60, // Sustained rate limit per minute
31-
"maxBurst": 120, // Maximum burst capacity
32-
"remaining": 118, // Current tokens available (up to maxBurst)
33-
"resetAt": "..." // When tokens next refill
30+
"requestsPerMinute": 150, // Sustained rate limit per minute
31+
"maxBurst": 300, // Maximum burst capacity
32+
"remaining": 298, // Current tokens available (up to maxBurst)
33+
"resetAt": "..." // When tokens next refill
3434
},
3535
"async": {
36-
"requestsPerMinute": 200, // Sustained rate limit per minute
37-
"maxBurst": 400, // Maximum burst capacity
38-
"remaining": 398, // Current tokens available
39-
"resetAt": "..." // When tokens next refill
36+
"requestsPerMinute": 1000, // Sustained rate limit per minute
37+
"maxBurst": 2000, // Maximum burst capacity
38+
"remaining": 1998, // Current tokens available
39+
"resetAt": "..." // When tokens next refill
4040
}
4141
},
4242
"usage": {
@@ -107,28 +107,28 @@ Query workflow execution logs with extensive filtering options.
107107
}
108108
],
109109
"nextCursor": "eyJzIjoiMjAyNS0wMS0wMVQxMjozNDo1Ni43ODlaIiwiaWQiOiJsb2dfYWJjMTIzIn0",
110-
"limits": {
111-
"workflowExecutionRateLimit": {
112-
"sync": {
113-
"requestsPerMinute": 60,
114-
"maxBurst": 120,
115-
"remaining": 118,
116-
"resetAt": "2025-01-01T12:35:56.789Z"
110+
"limits": {
111+
"workflowExecutionRateLimit": {
112+
"sync": {
113+
"requestsPerMinute": 150,
114+
"maxBurst": 300,
115+
"remaining": 298,
116+
"resetAt": "2025-01-01T12:35:56.789Z"
117+
},
118+
"async": {
119+
"requestsPerMinute": 1000,
120+
"maxBurst": 2000,
121+
"remaining": 1998,
122+
"resetAt": "2025-01-01T12:35:56.789Z"
123+
}
117124
},
118-
"async": {
119-
"requestsPerMinute": 200,
120-
"maxBurst": 400,
121-
"remaining": 398,
122-
"resetAt": "2025-01-01T12:35:56.789Z"
125+
"usage": {
126+
"currentPeriodCost": 1.234,
127+
"limit": 10,
128+
"plan": "pro",
129+
"isExceeded": false
123130
}
124-
},
125-
"usage": {
126-
"currentPeriodCost": 1.234,
127-
"limit": 10,
128-
"plan": "pro",
129-
"isExceeded": false
130131
}
131-
}
132132
}
133133
```
134134
</Tab>
@@ -188,15 +188,15 @@ Retrieve detailed information about a specific log entry.
188188
"limits": {
189189
"workflowExecutionRateLimit": {
190190
"sync": {
191-
"requestsPerMinute": 60,
192-
"maxBurst": 120,
193-
"remaining": 118,
191+
"requestsPerMinute": 150,
192+
"maxBurst": 300,
193+
"remaining": 298,
194194
"resetAt": "2025-01-01T12:35:56.789Z"
195195
},
196196
"async": {
197-
"requestsPerMinute": 200,
198-
"maxBurst": 400,
199-
"remaining": 398,
197+
"requestsPerMinute": 1000,
198+
"maxBurst": 2000,
199+
"remaining": 1998,
200200
"resetAt": "2025-01-01T12:35:56.789Z"
201201
}
202202
},
@@ -477,10 +477,10 @@ The API uses a **token bucket algorithm** for rate limiting, providing fair usag
477477

478478
| Plan | Requests/Minute | Burst Capacity |
479479
|------|-----------------|----------------|
480-
| Free | 10 | 20 |
481-
| Pro | 30 | 60 |
482-
| Team | 60 | 120 |
483-
| Enterprise | 120 | 240 |
480+
| Free | 30 | 60 |
481+
| Pro | 100 | 200 |
482+
| Team | 200 | 400 |
483+
| Enterprise | 500 | 1000 |
484484

485485
**How it works:**
486486
- Tokens refill at `requestsPerMinute` rate

apps/docs/content/docs/en/execution/costs.mdx

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -170,16 +170,16 @@ curl -X GET -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" htt
170170
"rateLimit": {
171171
"sync": {
172172
"isLimited": false,
173-
"requestsPerMinute": 25,
174-
"maxBurst": 50,
175-
"remaining": 50,
173+
"requestsPerMinute": 150,
174+
"maxBurst": 300,
175+
"remaining": 300,
176176
"resetAt": "2025-09-08T22:51:55.999Z"
177177
},
178178
"async": {
179179
"isLimited": false,
180-
"requestsPerMinute": 200,
181-
"maxBurst": 400,
182-
"remaining": 400,
180+
"requestsPerMinute": 1000,
181+
"maxBurst": 2000,
182+
"remaining": 2000,
183183
"resetAt": "2025-09-08T22:51:56.155Z"
184184
},
185185
"authType": "api"
@@ -206,11 +206,11 @@ curl -X GET -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" htt
206206

207207
Different subscription plans have different usage limits:
208208

209-
| Plan | Monthly Usage Limit | Rate Limits (per minute) |
210-
|------|-------------------|-------------------------|
211-
| **Free** | $20 | 5 sync, 10 async |
212-
| **Pro** | $100 | 10 sync, 50 async |
213-
| **Team** | $500 (pooled) | 50 sync, 100 async |
209+
| Plan | Monthly Usage Included | Rate Limits (per minute) |
210+
|------|------------------------|-------------------------|
211+
| **Free** | $20 | 50 sync, 200 async |
212+
| **Pro** | $20 (adjustable) | 150 sync, 1,000 async |
213+
| **Team** | $40/seat (pooled, adjustable) | 300 sync, 2,500 async |
214214
| **Enterprise** | Custom | Custom |
215215

216216
## Billing Model

apps/sim/app/workspace/[workspaceId]/providers/workspace-permissions-provider.tsx

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
'use client'
22

33
import type React from 'react'
4-
import { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react'
4+
import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react'
55
import { createLogger } from '@sim/logger'
66
import { useQueryClient } from '@tanstack/react-query'
77
import { useParams } from 'next/navigation'
8+
import { useSocket } from '@/app/workspace/providers/socket-provider'
89
import {
910
useWorkspacePermissionsQuery,
1011
type WorkspacePermissions,
@@ -57,14 +58,42 @@ export function WorkspacePermissionsProvider({ children }: WorkspacePermissionsP
5758
const [hasShownOfflineNotification, setHasShownOfflineNotification] = useState(false)
5859
const hasOperationError = useOperationQueueStore((state) => state.hasOperationError)
5960
const addNotification = useNotificationStore((state) => state.addNotification)
61+
const removeNotification = useNotificationStore((state) => state.removeNotification)
62+
const { isReconnecting } = useSocket()
63+
const reconnectingNotificationIdRef = useRef<string | null>(null)
6064

6165
const isOfflineMode = hasOperationError
6266

67+
useEffect(() => {
68+
if (isReconnecting && !reconnectingNotificationIdRef.current && !isOfflineMode) {
69+
const id = addNotification({
70+
level: 'error',
71+
message: 'Reconnecting...',
72+
})
73+
reconnectingNotificationIdRef.current = id
74+
} else if (!isReconnecting && reconnectingNotificationIdRef.current) {
75+
removeNotification(reconnectingNotificationIdRef.current)
76+
reconnectingNotificationIdRef.current = null
77+
}
78+
79+
return () => {
80+
if (reconnectingNotificationIdRef.current) {
81+
removeNotification(reconnectingNotificationIdRef.current)
82+
reconnectingNotificationIdRef.current = null
83+
}
84+
}
85+
}, [isReconnecting, isOfflineMode, addNotification, removeNotification])
86+
6387
useEffect(() => {
6488
if (!isOfflineMode || hasShownOfflineNotification) {
6589
return
6690
}
6791

92+
if (reconnectingNotificationIdRef.current) {
93+
removeNotification(reconnectingNotificationIdRef.current)
94+
reconnectingNotificationIdRef.current = null
95+
}
96+
6897
try {
6998
addNotification({
7099
level: 'error',
@@ -78,7 +107,7 @@ export function WorkspacePermissionsProvider({ children }: WorkspacePermissionsP
78107
} catch (error) {
79108
logger.error('Failed to add offline notification', { error })
80109
}
81-
}, [addNotification, hasShownOfflineNotification, isOfflineMode])
110+
}, [addNotification, removeNotification, hasShownOfflineNotification, isOfflineMode])
82111

83112
const {
84113
data: workspacePermissions,

apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/subscription/plan-configs.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,17 @@ import { SlackMonoIcon } from '@/components/icons'
1313
import type { PlanFeature } from '@/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/subscription/components/plan-card'
1414

1515
export const PRO_PLAN_FEATURES: PlanFeature[] = [
16-
{ icon: Zap, text: '25 runs per minute (sync)' },
17-
{ icon: Clock, text: '200 runs per minute (async)' },
16+
{ icon: Zap, text: '150 runs per minute (sync)' },
17+
{ icon: Clock, text: '1,000 runs per minute (async)' },
1818
{ icon: HardDrive, text: '50GB file storage' },
1919
{ icon: Building2, text: 'Unlimited workspaces' },
2020
{ icon: Users, text: 'Unlimited invites' },
2121
{ icon: Database, text: 'Unlimited log retention' },
2222
]
2323

2424
export const TEAM_PLAN_FEATURES: PlanFeature[] = [
25-
{ icon: Zap, text: '75 runs per minute (sync)' },
26-
{ icon: Clock, text: '500 runs per minute (async)' },
25+
{ icon: Zap, text: '300 runs per minute (sync)' },
26+
{ icon: Clock, text: '2,500 runs per minute (async)' },
2727
{ icon: HardDrive, text: '500GB file storage (pooled)' },
2828
{ icon: Building2, text: 'Unlimited workspaces' },
2929
{ icon: Users, text: 'Unlimited invites' },

0 commit comments

Comments
 (0)