What’s new in v4?
Read our blog post for an overview of the new features.Node.js support
Trigger.dev runs your tasks on specific Node.js versions:- v3: Uses Node.js
21.7.3
- v4: Uses Node.js
21.7.3
Wait tokens
In addition to waiting for a specific duration, or waiting for a child task to complete, you can now create and wait for a token to be completed, giving you more flexibility and the ability to wait for arbitrary conditions. For example, you can send the token to a Slack channel, and only complete the token when the user has clicked an “Approve” button. To wait for a token, you need to first create one using thewait.createToken
function:
Wait idempotency
You can now pass an idempotency key to any wait function, allowing you to skip waits if the same idempotency key is used again. This can be useful if you want to skip waits when retrying a task, for example:idempotencyKeyTTL
allows you to specify how long the idempotency key should be valid for. The default is 30 days.
Priority
You can now specify a priority when triggering a task. This allows you to prioritize certain tasks over others, and is useful if you want to ensure that certain tasks are executed before others.10
, the run will win over runs with a priority of 0
that were triggered within the last 10 seconds. A more concrete example:
We purposefully chose to use a time duration as the priority value instead of specifying priority
levels, because priority levels can cause “level starvation” where lower priority runs are never
executed because there are always higher priority runs in the queue.
Global lifecycle hooks
We’ve added a new way to register global lifecycle hooks that are executed for all runs, regardless of the task. Previously, this was only possible in thetrigger.config.ts
file, but now you can register them anywhere in your codebase:
init.ts
If you create a init.ts
file at the root of your trigger directory, it will be automatically loaded when a task is executed. This is useful if you want to register global lifecycle hooks, or initialize a database connection, etc.
init.ts
onWait and onResume
We’ve added two new lifecycle hooks that allow you to run code when a run is paused or resumed because of a wait:onComplete
We’ve added a new lifecycle hook that is executed when a run completes, regardless of whether it succeeded or failed:onCancel
Available in v4.0.0-beta.12 and later.
onCancel
hook that is called when a run is cancelled. This is useful if you want to clean up any resources that were allocated for the run.
onCancel
hook along with the signal
passed into the run function to interrupt a call to an external service, for example using the streamText function from the AI SDK:
onCancel
hook can optionally wait for the run
function to finish, and access the output of the run:
You will have up to 30 seconds to complete the
runPromise
in the onCancel
hook. After that
point the process will be killed.Improved middleware and locals
Our task middleware system is now much more useful. Previously it only ran “around” therun
function, but now we’ve hoisted it to the top level and it now runs before/after all the other hooks.
We’ve also added a new locals
API that allows you to share data between middleware and hooks.
db.ts
run
function and all your hooks (global or task specific) you can access the database client using getDb()
:
Hidden tasks
Previously, you were required to export the task from a file in your trigger directory to be able to execute it. We’ve changed the way tasks are indexed and this requirement has been removed. So you can now just define a task without exporting it, and everything will still work:trigger/my-task.ts
trigger/my-task.ts
trigger/my-task.ts
useWaitToken
We’ve added a newuseWaitToken
react hook that allows you to complete a wait token from a React component, using a Public Access Token.
backend.ts
useWaitToken
hook in your frontend code:
frontend.tsx
ai.tool
We’ve added a new ai.tool
function that allows you to create an AI tool from an existing schemaTask
to use with the Vercel AI SDK:
experimental_toToolResultContent
option to the ai.tool
function to customize the content of the tool result:
ai.currentToolOptions()
function:
ai.tool
is compatible with schemaTask
’s defined with Zod and ArkType schemas, or any schemas
that implement a .toJsonSchema()
function.How to migrate to v4
First read the deprecations, breaking changes, and known issues sections below. We recommend the following steps to migrate to v4:- Install the v4 package.
- Run the
trigger dev
CLI command and test your tasks locally, fixing any breaking changes. - Deploy to the staging environment and test your tasks in staging, fixing any breaking changes. (this step is optional, but highly recommended)
- Once you’ve verified that v4 is working as expected, you should deploy your application backend with the updated v4 package.
- Once you’ve deployed your application backend, you should deploy your tasks to the production environment.
Once v4 is activated in your environment, there will be a period of time where old runs will
continue to execute using v3, while new runs will use v4. Because these engines use completely
different underlying queues and concurrency models, it’s possible you may have up to double the
amount of concurrently executing runs. Once the runs drain from the old run engine, the
concurrency will return to normal.
Installation
To opt-in to using v4, you will need to update your dependencies to the latest version of thev4-beta
tag.
You will need to do this for all your
@trigger.dev/*
packages. v4-beta
version of the trigger.dev
CLI package:
Known issues
During the beta we will be tracking issues and releasing regular fixes.Deprecations
We’ve deprecated the following APIs:@trigger.dev/sdk/v3
We’ve deprecated the@trigger.dev/sdk/v3
import path and moved to a new path:
handleError
and init
We’ve renamed the handleError
hook to catchError
to better reflect that it can catch and react to errors. handleError
will be removed in a future version.
init
was previously used to initialize data used in the run function:
locals
API and middleware. See the Improved middleware and locals section for more details.
toolTask
We’ve deprecated thetoolTask
function, which created both a Trigger.dev task and a tool compatible with the Vercel AI SDK:
toolTask
function with the ai.tool
function, which creates an AI tool from an existing schemaTask
. See the ai.tool section for more details.
Breaking changes
Queue changes
Previously, it was possible to specify a queue name of a queue that did not exist, along with a concurrency limit. The queue would then be created “on-demand” with the specified concurrency limit. If the queue did exist, the concurrency limit of the queue would be updated to the specified value:queue
function:
Concurrency changes
We’ve changed a few things around how concurrency is managed at the environment and queue level:- Environment concurrency limits are now “burstable” above the base concurrency limit. The default burst factor is 2.0, meaning that the environment concurrency limit can be up to 2x the base concurrency limit. So if your base concurrency limit is 10, the environment concurrency limit can be up to 20.
- Each individual queue has a maximum concurrency limit of the environment base concurrency limit, NOT the burstable limit. So if your base concurrency limit is 10, the queue concurrency limit can be up to 10. This means if you don’t set the queue concurrency limit, it will default to the environment base concurrency limit.
- The only time we “release” concurrency is when a run is checkpointed. This means that if you have a run that is waiting on a waitpoint, and the run is checkpointed, the concurrency will be released back into the queue, allowing other runs to execute/resume. We release the concurrency back to the queue and the environment.
concurrencyLimit
of 1, you can only have exactly 1 run executing at a time, but you may have more than 1 run in the WAITING
state that belongs to that queue. Runs are only transitioned to the WAITING
state when they are waiting on a waitpoint and have been checkpointed.
New Run Statuses
We’ve done some work cleaning up the run statuses. The new statuses are:PENDING_VERSION
: Task is waiting for a version update because it cannot execute without additional information (task, queue, etc.).QUEUED
: Task is waiting to be executed by a worker.DEQUEUED
: Task has been dequeued and is being sent to a worker to start executing.EXECUTING
: Task is currently being executed by a worker.WAITING
: Task has been paused by the system, and will be resumed by the system.COMPLETED
: Task has been completed successfully.CANCELED
: Task has been canceled by the user.FAILED
: Task has failed to complete, due to an error in the task code.CRASHED
: Task has crashed and won’t be retried, most likely the worker ran out of resources, e.g. memory or storage.SYSTEM_FAILURE
: Task has failed to complete, due to an error in the systemDELAYED
: Task has been scheduled to run at a specific time.EXPIRED
: Task has expired and won’t be executed,TIMED_OUT
: Task has reached its maxDuration and has been stopped.
WAITING_FOR_DEPLOY
: This is no longer used, and is replaced byPENDING_VERSION
FROZEN
: This is no longer used, and is replaced byWAITING
INTERRUPTED
: This is no longer usedREATTEMPTING
: This is no longer used, and is replaced byEXECUTING
isQueued
: Returns true when the status isQUEUED
,PENDING_VERSION
, orDELAYED
isExecuting
: Returns true when the status isEXECUTING
,DEQUEUED
. These count against your concurrency limits.isWaiting
: Returns true when the status isWAITING
. These do not count against your concurrency limits.isCompleted
: Returns true when the status is any of the completed statuses.isCanceled
: Returns true when the status isCANCELED
isFailed
: Returns true when the status is any of the failed statuses.isSuccess
: Returns true when the status isCOMPLETED
Lifecycle hooks
We’ve changed the function signatures of the lifecycle hooks to be more consistent and easier to use, by unifying all the parameters into a single object that can be destructured. Previously, hooks received a payload as the first argument and then an additional object as the second argument:Context changes
We’ve made a few small changes to thectx
object:
ctx.attempt.id
andctx.attempt.status
have been removed.ctx.attempt.number
is still available.ctx.task.exportName
has been removed (since we no longer require tasks to be exported to be triggered).
BatchTrigger changes
ThebatchTrigger
function no longer returns a runs
list directly. In v3, you could access the runs directly from the batch handle:
runs.list()
method to get the list of runs:
v4 beta Changelog
Trigger.dev v4
release.
Please see our upgrade to v4 docs to view the full changelog. Run Engine 2.0 (alpha)
(#1575), improved warm start times by
eagerly creating the child TaskRunProcess when a previous run as completed
(#1879), and new lifecycle hooks
(#1817).
Release
v4.0.0-beta.1.
Fixed init.ts in custom trigger dirs and init command now correctly installs v4-beta packages
(#1914). Updated nypm package to support
test-based bun.lock files and handle flush errors gracefully in dev
(#1914).
Release
v4.0.0-beta.2.
Managed run controller performance and reliability improvements
(#1927).
Release
v4.0.0-beta.3.
Improved usage flushing (#1931) and
fixed stalled run detection (#1934).
Release
v4.0.0-beta.5.
Updated dependencies with various bug fixes and improvements.
Release
v4.0.0-beta.6.
The dev command now uses the platform-provided engine URL
(#1949).
Release
v4.0.0-beta.7.
Fixed runLimiter check on dequeueRuns
(#1953) and QUEUED status snapshot
handler (#1963).
Release
v4.0.0-beta.8.
Prevented large outputs from overwriting each other
(#1971).
Release
v4.0.0-beta.9.
Fixed default machine config indexing
(#1979).
Release
v4.0.0-beta.10.
TriggerApiError 4xx errors no longer cause tasks to be retried
(#1970). Fixed polling interval reset
bug that could create duplicate intervals, protected against unexpected attempt number changes,
and prevented run execution zombies after warm starts
(#1987).
Release
v4.0.0-beta.11.
Updated dependencies with various bug fixes and improvements.
Release
v4.0.0-beta.12.
Display clickable links in Cursor terminal
(#1998) and added AI assistance link
when you have build errors (#1925).
Added validation when passing a directory to deploy command with helpful hints
(#2013).
Release
v4.0.0-beta.13.
Correctly resolved waitpoints that come in early, ensured correct state before requesting
suspension, and fixed race conditions in snapshot processing
(#2006). Always print full deploy logs
in CI (#2006).
Release
v4.0.0-beta.14.
Updated dependencies with various bug fixes and improvements.
Release
v4.0.0-beta.15.
Added external log exporters and fixed missing external trace exporters in deployed tasks
(#2038). Log images sizes for
self-hosted deploys (#1764) and fixed
init.ts auto-import for deployed workers
(#2041).
Release
v4.0.0-beta.16.
Fixed init.ts detection when using the sentry esbuild plugin
(#2051).
Release
v4.0.0-beta.17.
Exposed esbuild
keepNames
(#2091) and
minify
options (experimental) (#2091).
Added experimental_autoDetectExternal
trigger config option
(#2083) and output esbuild metafile,
which can be inspected after deploy --dry run
(#2087).Release
v4.0.0-beta.18.
Fixed dev runs (#2094).
Release
v4.0.0-beta.19.
Added import timings and bundle size analysis - the dev command now warns about slow imports
(#2114). Fixed metadata collapsing
correctness (#2115), added support for
Preview branches in v4 projects (#2086),
can now set project ref using the TRIGGER_PROJECT_REF env var
(#2109), and fixed
syncEnvVars
for
non-preview deployments (#2131).Release
v4.0.0-beta.20.
Updated dependencies with various bug fixes and improvements.
Release
v4.0.0-beta.21.
Runtime agnostic SDK config via env vars
(#2132) and fixed update command version
range handling (#2153). Resolved issue
where CLI could get stuck during deploy finalization, unified local and remote build logic with
multi-platform build support, improved switch command which now accepts profile name as an
argument, registry configuration is now fully managed by the webapp, the deploy
--self-hosted
flag is no longer required, and enhanced deployment error reporting and image digest retrieval
(#2138). Updated profile switcher
(#2150).Release
v4.0.0-beta.22.
Fix update command version mismatch detection
(#2199). Add project details to the
whoami command (#2231). Serialize
metadata to prevent invalid metadata from breaking run completions
(#2219)This release also includes a new experimental You can also pass an object to
processKeepAlive
option, which allows you to
keep the process alive after the run has completed for the next warm start, which makes warm starts even faster.Currently during a warm start, we still recreate the actual task run process between runs, leading to a completely fresh global environment for each run. This experimental option will keep the task run process alive between run executions, leading to even faster warm starts. This option is respected in both the dev
CLI and in deployed tasks.To enable this option, add this to your trigger.config.ts
:experimental_processKeepAlive
to provide more options:Gotchas
- Be careful with memory usage and memory leaks, as this will cause memory to persist across run executions.
- It’s possible different tasks get executed in the same persisted process.
- If you configure any 3rd party SDKs globally using env vars for API keys, those SDKs will not change between runs. So if you change an env var between runs, the SDK will be “stale” and continue using the old env var value. Instead, you should initialize SDKs using env vars at runtime (in any of the lifecycle hooks or inside the
run
function of a task. - Cancelling a task will cause the task run process to be restarted. Exiting the process is the only reliable way to actually stop a running function from stopping.
- This DOES NOT effect cold starts, warm starts only will be improved.
Release
v4.0.0-beta.23.
- fix: Logging large objects is now much more performant and uses less memory (#2263)
- New internal idempotency implementation for trigger and batch trigger to prevent request retries from duplicating work (#2256)
- Enhance deploy command output to better distinguish between local and remote builds (#2254)
- Fixes a bug that would allow processes that had OOM errors to be incorrectly reused when experimental_processKeepAlive was enabled (#2261)
- Add runtime version detection for display in the dashboard (#2254)
-
Update base images to latest compatible versions. The
node-22
runtime now uses v22.16.0 andbun
uses the latest v1.2.18 release. The defaultnode
runtime is unchanged and points at v21.7.3. (#2254) -
Fail fast in CI when running deploy with missing
TRIGGER_ACCESS_TOKEN
and add useful error message with link to docs (#2258)
Release
v4.0.0-beta.24.
-
Removes the
releaseConcurrencyOnWaitpoint
option on queues and thereleaseConcurrency
option on various wait functions. Replaced with the following default behavior: (#2284)- Concurrency is never released when a run is first blocked via a waitpoint, at either the env or queue level.
- Concurrency is always released when a run is checkpointed and shutdown, at both the env and queue level.
PENDING_VERSION
: Task is waiting for a version update because it cannot execute without additional information (task, queue, etc.)QUEUED
: Task is waiting to be executed by a workerDEQUEUED
: Task has been dequeued and is being sent to a worker to start executing.EXECUTING
: Task is currently being executed by a workerWAITING
: Task has been paused by the system, and will be resumed by the systemCOMPLETED
: Task has been completed successfullyCANCELED
: Task has been canceled by the userFAILED
: Task has failed to complete, due to an error in the systemCRASHED
: Task has crashed and won’t be retried, most likely the worker ran out of resources, e.g. memory or storageSYSTEM_FAILURE
: Task has failed to complete, due to an error in the systemDELAYED
: Task has been scheduled to run at a specific timeEXPIRED
: Task has expired and won’t be executedTIMED_OUT
: Task has reached it’s maxDuration and has been stopped
WAITING_FOR_DEPLOY
: This is no longer used, and is replaced byPENDING_VERSION
FROZEN
: This is no longer used, and is replaced byWAITING
INTERRUPTED
: This is no longer usedREATTEMPTING
: This is no longer used, and is replaced byEXECUTING
isQueued
: Returns true when the status isQUEUED
,PENDING_VERSION
, orDELAYED
isExecuting
: Returns true when the status isEXECUTING
,DEQUEUED
. These count against your concurrency limits.isWaiting
: Returns true when the status isWAITING
. These do not count against your concurrency limits.isCompleted
: Returns true when the status is any of the completed statuses.isCanceled
: Returns true when the status isCANCELED
isFailed
: Returns true when the status is any of the failed statuses.isSuccess
: Returns true when the status isCOMPLETED
EXECUTING
orDEQUEUED
. - Added runs.list filtering for queue and machine (#2277)
Release
v4.0.0-beta.25.
- Gracefully shutdown task run processes using SIGTERM followed by SIGKILL after a 1s timeout. This also prevents cancelled or completed runs from leaving orphaned task run processes behind (#2299)
Release
v4.0.0-beta.26.
- Allow any runs to finish after SIGTERM but disable warm starts (#2316)
- Switch to profile after successful login (#2192)
- Fixed importing from runEngine/index.js breaking non-node runtimes (#2328)
- Added and cleaned up the run ctx param (#2322):
- New optional properties
ctx.run.parentTaskRunId
andctx.run.rootTaskRunId
reference the current run’s root/parent ID - Removed deprecated properties from
ctx
- Added a new
ctx.deployment
object that contains information about the deployment associated with the run - Updated
metadata.root
andmetadata.parent
to work even when the run is a “root” run (meaning it doesn’t have a parent or a root associated run)
- New optional properties
Release
v4.0.0-beta.27.
- All experimental flags have been promoted to non-experimental, but the experimental ones still work (for now).
keepNames
andautoDetectExternal
now default to true. (#2371) - Improve playwright non-headless chrome installation (#2347)
- Upgrade to zod 3.25.76 (#2352)
- External Trace Correlation & OpenTelemetry Package Updates. (#2334)
- Add jsonSchema support when indexing tasks (#2353)
- Removed triggerAndPoll. It was never recommended so it’s been removed. (#2379)
- Specify a region override when triggering a run (#2366)