Upgrade
npx trigger.dev@latest update # npm
pnpm dlx trigger.dev@latest update # pnpm
yarn dlx trigger.dev@latest update # yarn
bunx trigger.dev@latest update # bunSelf-hosted Docker image: ghcr.io/triggerdotdev/trigger.dev:v4.4.5
Release notes
Read the full release notes: https://trigger.dev/changelog/v4-4-5
What's changed
Breaking changes
- Add server-side deprecation gate for deploys from v3 CLI versions (gated by
DEPRECATE_V3_CLI_DEPLOYS_ENABLED). v4 CLI deploys are unaffected. (#3415)
Improvements
- Add
--no-browserflag toinitandloginto skip auto-opening the browser during authentication. Also error loudly wheninitis run without--yesunder non-TTY stdin (previously default-and-exited silently, leaving the project half-initialized). Both commands now show anExamplessection in--help. (#3483) - Add
isReplayboolean to the run context (ctx.run.isReplay), derived from the existingreplayedFromTaskRunFriendlyIddatabase field. Defaults tofalsefor backwards compatibility. (#3454) - Redact the
resolveWaitpointruntime log so it only emitsidandtypeinstead of the full completed waitpoint. Previously the log printed the entire waitpoint (includingoutput) to stdout in production runs, which could leak sensitive payloads. The value returned bywait.forToken()is unchanged. (#3490) - Add
SessionIdfriendly ID generator and schemas for the new durable Session primitive. Exported from@trigger.dev/core/v3/isomorphicalongsideRunId,BatchId, etc. Ships theCreateSessionStreamWaitpointrequest/response schemas alongside the main Session CRUD. (#3417) - Truncate large error stacks and messages to prevent OOM crashes. Stack traces are capped at 50 frames (keeping top 5 + bottom 45 with an omission notice), individual stack lines at 1024 chars, and error messages at 1000 chars. Applied in parseError, sanitizeError, and OTel span recording. (#3405)
Server changes
These changes affect the self-hosted Docker image and Trigger.dev Cloud:
-
Add a "Back office" tab to
/adminand a per-organization detail page at/admin/back-office/orgs/:orgId. The first action available on that page is editing the org's API rate limit: admins can save atokenBucketoverride (refill rate, interval, max tokens) and see a plain-English preview of the resulting sustained rate and burst allowance. Writes are audit-logged via the server logger. (#3434) -
Optional
DEPLOY_REGISTRY_ECR_DEFAULT_REPOSITORY_POLICYenv var to apply a default repository policy when the webapp creates new ECR repos (#3467) -
Ship the Errors page to all users, with a polish + bug-fix pass: pinned "No channel" item in the Slack alert channel picker, viewer-timezone alert timestamps via Slack's
<!date^>token, Activity sparkline peak tooltip, centered loading spinner and bug-icon empty state on the error detail page, ellipsis on the Configure alerts trigger. (#3477) -
Configure the set of machine presets to build boot snapshots for at deploy time via
COMPUTE_TEMPLATE_MACHINE_PRESETS(CSV of preset names, defaultsmall-1x). UseCOMPUTE_TEMPLATE_MACHINE_PRESETS_REQUIRED(CSV, default = full PRESETS list) to scope which preset failures fail a required-mode deploy. Optional preset failures are logged and don't block the deploy. (#3492) -
Regenerating a RuntimeEnvironment API key no longer invalidates the previous key immediately. The old key is recorded in a new
RevokedApiKeytable with a 24 hour grace window, andfindEnvironmentByApiKeyfalls back to it when the submitted key doesn't match any live environment. The grace window can be ended early (or extended) by updatingexpiresAton the row. (#3420) -
Add the
Sessionprimitive — a durable, task-bound, bidirectional I/O channel that outlives a single run and acts as the run manager forchat.agent. Ships the PostgresSession+SessionRuntables, ClickHousesessions_v1+ replication service, thesessionsJWT scope, and the public CRUD + realtime routes (/api/v1/sessions,/realtime/v1/sessions/:session/:io) includingend-and-continuefor server-orchestrated run handoffs and session-stream waitpoints. (#3417) -
Add
KUBERNETES_POD_DNS_NDOTS_OVERRIDE_ENABLEDflag (off by default) that overrides the cluster default and setsdnsConfig.options.ndotson runner pods (defaulting to 2, configurable viaKUBERNETES_POD_DNS_NDOTS). Kubernetes defaults pods tondots: 5, so any name with fewer than 5 dots — including typical external domains likeapi.example.com— is first walked through every entry in the cluster search list (<ns>.svc.cluster.local,svc.cluster.local,cluster.local) before being tried as-is, turning one resolution into 4+ CoreDNS queries (×2 with A+AAAA). Using a lowerndotsvalue reduces DNS query amplification in thecluster.localzone.Note: before enabling, make sure no code path relies on search-list expansion for names with dots ≥ the configured value — those names will hit their as-is form first and could resolve externally before falling back to the cluster search path. (#3441)
-
Vercel integration option to disable auto promotions (#3376)
-
Make it clear in the admin that feature flags are global and should rarely be changed. (#3408)
-
Admin worker groups API: add GET loader and expose more fields on POST. (#3390)
-
Add 60s fresh / 60s stale SWR cache to
getEntitlementinplatform.v3.server.ts. Eliminates a synchronous billing-service HTTP round trip on every trigger. Reuses the existingplatformCache(LRU memory + Redis) pattern already used forlimitsandusage. Cache key is${orgId}. Errors return a permissive{ hasAccess: true }fallback (existing behavior) and are also cached to prevent thundering-herd on billing outages. (#3388) -
Show a
MicroVMbadge next to the region name on the regions page. (#3407) -
Increase default maximum project count per organization from 10 to 25 (#3409)
-
Merge execution snapshot creation into the dequeue taskRun.update transaction, reducing 2 DB commits to 1 per dequeue operation (#3395)
-
Add per-worker Node.js heap metrics to the OTel meter —
nodejs.memory.heap.used,nodejs.memory.heap.total,nodejs.memory.heap.limit,nodejs.memory.external,nodejs.memory.array_buffers,nodejs.memory.rss. Host-metrics only publishes RSS, which overstates V8 heap by the external + native footprint; these give direct heap visibility per cluster worker soNODE_MAX_OLD_SPACE_SIZEcan be sized against observed heap peaks rather than RSS. (#3437) -
Tag Prisma spans with
db.datasource: "writer" | "replica"so monitors and trace queries can distinguish the writer pool from the replica pool. Applies to allprisma:engine:*spans (includingprisma:engine:connectionused by the connection-pool monitors) and the outerprisma:client:operationspan. (#3422) -
Clarify the cross-region intent in the Terraform and AI-prompt helpers on the Add Private Connection page. Both already default
supported_regionsto["us-east-1", "eu-central-1"]; added an inline comment / parenthetical so the user understands why both regions are listed (Trigger.dev runs in both, so the service must be consumable from either). (#3465) -
Add
RUN_ENGINE_READ_REPLICA_SNAPSHOTS_SINCE_ENABLEDflag (default off) to route the Prisma reads insideRunEngine.getSnapshotsSincethrough the read-only replica client. Offloads the snapshot polling queries (fired by every running task runner) from the primary. When disabled, behavior is unchanged. (#3423) -
Stop creating TaskRunTag records and _TaskRunToTaskRunTag join table entries during task triggering. The denormalized runTags string array on TaskRun already stores tag names, making the M2M relation redundant write overhead. (#3369)
-
Stop writing per-tick state (
lastScheduledTimestamp,nextScheduledTimestamp,lastRunTriggeredAt) onTaskScheduleandTaskScheduleInstance. The schedule engine now carries the previous fire time forward via the worker queue payload, eliminating ~270K dead-tuple-driven autovacuums per year on these hot tables and the associatedIO:XactSyncmini-spikes on the writer. Customer-facingpayload.lastTimestampsemantics are unchanged. (#3476) -
Replace the expensive DISTINCT query for task filter dropdowns with a dedicated TaskIdentifier registry table backed by Redis. Environments migrate automatically on their next deploy, with a transparent fallback to the legacy query for unmigrated environments. Also fixes duplicate dropdown entries when a task changes trigger source, and adds active/archived grouping for removed tasks. Moves BackgroundWorkerTask reads in the trigger hot path to the read replica. (#3368)
-
Public Access Tokens (PATs) minted before an API key rotation now keep working during the 24h grace window.
validatePublicJwtKeyfalls back to any non-expiredRevokedApiKeyrows for the signing environment when the primary signature check against the env's currentapiKeyfails. The fallback query only runs on the failure path, so the hot success path is unchanged. (#3464) -
Batch items that hit the environment queue size limit now fast-fail without
retries and without creating pre-failed TaskRuns. (#3352) -
Show the cancel button in the runs list for runs in
DEQUEUEDstatus.DEQUEUEDwas missing fromNON_FINAL_RUN_STATUSESso the list hid the button even though the single run page allowed it. (#3421) -
Reduce 5xx feedback loops on hot debounce keys by quantizing
delayUntil,
adding an unlocked fast-path skip, and gracefully handling redlock
contention inhandleDebounceso the SDK no longer retries into a herd. (#3453) -
Fix RSS memory leak in the realtime proxy routes.
/realtime/v1/runs,/realtime/v1/runs/:id, and/realtime/v1/batches/:idcalledfetch()into Electric with no abort signal, so when a client disconnected mid long-poll, undici kept the upstream socket open and buffered response chunks that would never be consumed — retained only in RSS, invisible to V8 heap tooling. ThreadgetRequestAbortSignal()throughRealtimeClient.streamRun/streamRuns/streamBatchtolongPollingFetchand cancel the upstream body in the error path. Isolated reproducer showed ~44 KB retained per leaked request; signal propagation releases it cleanly. (#3442) -
Fix memory leak where every aborted SSE connection pinned the full request/response graph on Node 20, caused by
AbortSignal.any()insse.tsretaining its source signals indefinitely (see nodejs/node#54614, nodejs/node#55351). Also clear thesetTimeout(abort)timer inentry.server.tsxso successful HTML renders don't pin the React tree for 30s per request. (#3430) -
Preserve filters on the queues page when submitting modal actions. (#3471)
-
Fix Redis connection leak in realtime streams and broken abort signal propagation.
Redis connections: Non-blocking methods (ingestData, appendPart, getLastChunkIndex) now share a single Redis connection instead of creating one per request. streamResponse still uses dedicated connections (required for XREAD BLOCK) but now tears them down immediately via disconnect() instead of graceful quit(), with a 15s inactivity fallback.
Abort signal: request.signal is broken in Remix/Express due to a Node.js undici GC bug (nodejs/node#55428) that severs the signal chain when Remix clones the Request internally. Added getRequestAbortSignal() wired to Express res.on("close") via httpAsyncStorage, which fires reliably on client disconnect. All SSE/streaming routes updated to use it. (#3399)
-
Prevent dashboard crash (React error #31) when span accessory item text is not a string. Filters out malformed accessory items in SpanCodePathAccessory instead of passing objects to React as children. (#3400)
-
Upgrade Remix packages from 2.1.0 to 2.17.4 to address security vulnerabilities in React Router (#3372)
-
Fix Vercel integration settings page (remove redundant section toggles) and improve the Vercel onboarding flow so the modal closes after connecting a GitHub repo and the marketplace
nextURL is preserved across the GitHub app install redirect. (#3424)
All packages: v4.4.5
@trigger.dev/build, @trigger.dev/core, @trigger.dev/python, @trigger.dev/react-hooks, @trigger.dev/redis-worker, @trigger.dev/rsc, @trigger.dev/schema-to-json, @trigger.dev/sdk, trigger.dev
Contributors
Eric Allam, @nicktrn, @isshaddad, devin-ai-integration[bot], Matt Aitken, Oskar Otwinowski, @D-K-P, @ThullyoCunha, github-actions[bot], Saadi Myftija
Full changelog: v4.4.4...v4.4.5