improvement(timeouts): sync to 50 min, self-hosted maxed out (#3133)

* improvement(timeouts): sync to 50 min, self-hosted maxed out

* update env vars
This commit is contained in:
Vikhyath Mondreti
2026-02-04 11:27:41 -08:00
committed by GitHub
parent c77e351067
commit 362f4c2918
4 changed files with 18 additions and 12 deletions

View File

@@ -220,9 +220,9 @@ Workflows have maximum execution time limits based on your subscription plan:
| Plan | Sync Execution | Async Execution |
|------|----------------|-----------------|
| **Free** | 5 minutes | 10 minutes |
| **Pro** | 60 minutes | 90 minutes |
| **Team** | 60 minutes | 90 minutes |
| **Enterprise** | 60 minutes | 90 minutes |
| **Pro** | 50 minutes | 90 minutes |
| **Team** | 50 minutes | 90 minutes |
| **Enterprise** | 50 minutes | 90 minutes |
**Sync executions** run immediately and return results directly. These are triggered via the API with `async: false` (default) or through the UI.
**Async executions** (triggered via API with `async: true`, webhooks, or schedules) run in the background. Async time limits are up to 2x the sync limit, capped at 90 minutes.

View File

@@ -15,7 +15,7 @@ import type { PlanFeature } from '@/app/workspace/[workspaceId]/w/components/sid
export const PRO_PLAN_FEATURES: PlanFeature[] = [
{ icon: Zap, text: '150 runs per minute (sync)' },
{ icon: Clock, text: '1,000 runs per minute (async)' },
{ icon: Timer, text: '60 min sync execution limit' },
{ icon: Timer, text: '50 min sync execution limit' },
{ icon: HardDrive, text: '50GB file storage' },
{ icon: Users, text: 'Unlimited invites' },
{ icon: Database, text: 'Unlimited log retention' },
@@ -24,7 +24,7 @@ export const PRO_PLAN_FEATURES: PlanFeature[] = [
export const TEAM_PLAN_FEATURES: PlanFeature[] = [
{ icon: Zap, text: '300 runs per minute (sync)' },
{ icon: Clock, text: '2,500 runs per minute (async)' },
{ icon: Timer, text: '60 min sync execution limit' },
{ icon: Timer, text: '50 min sync execution limit' },
{ icon: HardDrive, text: '500GB file storage (pooled)' },
{ icon: Users, text: 'Unlimited invites' },
{ icon: Database, text: 'Unlimited log retention' },

View File

@@ -171,9 +171,9 @@ export const env = createEnv({
RATE_LIMIT_ENTERPRISE_ASYNC: z.string().optional().default('5000'), // Enterprise tier async API executions per minute
EXECUTION_TIMEOUT_FREE: z.string().optional().default('300'),
EXECUTION_TIMEOUT_PRO: z.string().optional().default('3600'),
EXECUTION_TIMEOUT_TEAM: z.string().optional().default('3600'),
EXECUTION_TIMEOUT_ENTERPRISE: z.string().optional().default('3600'),
EXECUTION_TIMEOUT_PRO: z.string().optional().default('3000'),
EXECUTION_TIMEOUT_TEAM: z.string().optional().default('3000'),
EXECUTION_TIMEOUT_ENTERPRISE: z.string().optional().default('3000'),
// Knowledge Base Processing Configuration - Shared across all processing methods
KB_CONFIG_MAX_DURATION: z.number().optional().default(600), // Max processing duration in seconds (10 minutes)

View File

@@ -1,4 +1,5 @@
import { env } from '@/lib/core/config/env'
import { isBillingEnabled } from '@/lib/core/config/feature-flags'
import type { SubscriptionPlan } from '@/lib/core/rate-limiter/types'
interface ExecutionTimeoutConfig {
@@ -8,9 +9,9 @@ interface ExecutionTimeoutConfig {
const DEFAULT_SYNC_TIMEOUTS_SECONDS = {
free: 300,
pro: 3600,
team: 3600,
enterprise: 3600,
pro: 3000,
team: 3000,
enterprise: 3000,
} as const
const ASYNC_MULTIPLIER = 2
@@ -56,6 +57,9 @@ export function getExecutionTimeout(
plan: SubscriptionPlan | undefined,
type: 'sync' | 'async' = 'sync'
): number {
if (!isBillingEnabled) {
return EXECUTION_TIMEOUTS.enterprise[type]
}
return EXECUTION_TIMEOUTS[plan || 'free'][type]
}
@@ -63,7 +67,9 @@ export function getMaxExecutionTimeout(): number {
return EXECUTION_TIMEOUTS.enterprise.async
}
export const DEFAULT_EXECUTION_TIMEOUT_MS = EXECUTION_TIMEOUTS.free.sync
export const DEFAULT_EXECUTION_TIMEOUT_MS = isBillingEnabled
? EXECUTION_TIMEOUTS.free.sync
: EXECUTION_TIMEOUTS.enterprise.sync
export function isTimeoutError(error: unknown): boolean {
if (!error) return false