improvement(schedules): jitter scheduled execution starts by 30s#4750
Conversation
Cron schedules all fire on the same boundary (e.g. every :00), stampeding the Postgres connection pool at the top of each minute/hour. Spread each due schedule's start across a [0, 30s) window via trigger.dev's delay option (no compute billed during the delay). Wires the previously-unused EnqueueOptions.delayMs through the trigger.dev backend.
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
PR SummaryLow Risk Overview The scheduled execute API now sets Reviewed by Cursor Bugbot for commit 1aa959a. Bugbot is set up for automated code reviews on this repo. Configure here. |
Greptile SummaryThis PR spreads scheduled workflow executions across a random [0, 30s) window to prevent DB connection-pool stampedes at the top of each cron boundary. The change is minimal and surgical: a
Confidence Score: 5/5Safe to merge. The change is narrow and additive — it only affects how trigger.dev schedules the start of each execution, not the execution logic itself. Two files changed, both in single-digit lines. The delayMs field was already typed in EnqueueOptions and is silently ignored by the database backend, so dev/test environments are unaffected. The trigger.dev guard (delayMs > 0) is correct, the absolute-timestamp approach to expressing the delay is valid, and the idempotency key path means duplicate enqueues during the delay window are handled correctly. No files require special attention. Important Files Changed
Sequence DiagramsequenceDiagram
participant Cron as Cron Trigger
participant Route as /api/schedules/execute
participant DB as Postgres
participant Queue as TriggerDevJobQueue
participant TDev as trigger.dev
Cron->>Route: GET (every minute, all schedules fire at :00)
Route->>DB: claimWorkflowSchedules (SELECT FOR UPDATE SKIP LOCKED)
DB-->>Route: [schedule1, schedule2, ..., scheduleN]
loop for each claimed schedule
Route->>Queue: "enqueue('schedule-execution', payload, { delayMs: rand[0,30s) })"
Queue->>TDev: "tasks.trigger(taskId, payload, { delay: Date.now() + delayMs })"
TDev-->>Queue: handle.id
Queue-->>Route: jobId
end
Note over TDev: Executions spread across :00-:30 instead of all hitting DB at :00
Reviews (1): Last reviewed commit: "improvement(schedules): jitter scheduled..." | Re-trigger Greptile |
Summary
Cron schedules all fire on the same boundary (e.g. every :00), stampeding the Postgres connection pool at the top of each minute/hour. Spread each due schedule's start across a [0, 30s) window via trigger.dev's delay option (no compute billed during the delay). Wires the previously-unused EnqueueOptions.delayMs through the trigger.dev backend.
Type of Change
Testing
Checklist
Screenshots/Videos