Trigger.dev v4.5.12

Execution windows on declarative scheduled tasks, deploy tagging with --external-id, skew version protection, and Node.js 24 as the default for new projects.

1 new feature, 5 improvements, 4 bug fixes, and 17 server changes.

Highlights

Execution windows for declarative scheduled tasks

Declarative scheduled tasks now support configurable execution windows. Instead of running at precisely the CRON time, each run gets assigned a stable slot within the window, so the task reliably runs at the same offset on every invocation.

The Schedule API now exposes both the nominal CRON time (when the pattern fires) and the assigned execution time. The run payload gives you access to both. The dashboard shows the configured window for each schedule and lists upcoming assignment times.

(#4572)

Scheduled tasks docs

Improvements

  • trigger.dev deploy --external-id tags a deployment with an identifier you control: a commit SHA, a CI run ID, a release tag. Deploying the same ID twice builds nothing and reports the existing version instead; use --force to rebuild. (#4663)
  • trigger projects list shows the current Production runtime for every accessible project. Add --needs-update to filter for projects still on Node.js 21. (#4659)
  • New projects from trigger init now use Node.js 24 by default. Deployments without an explicit runtime pick up their project's configured default. (#4649)
  • Deployment builds now use custom base layer images and skip system package installation on every build, improving layer cache hits and pulling faster on worker nodes. (#4602)
  • Set TRIGGER_EXTERNAL_DEPLOYMENT_ID to pin runs to the deployment your calling code came from, so an old release never triggers tasks from a new one. Set TRIGGER_AUTOMATIC_SKEW_VERSION_PROTECTION=1 to detect the commit automatically on Vercel and most CI systems. Runs triggered before the build finishes wait, then start pinned. (#4664)

Bug fixes

  • Unrelated runs no longer get merged into a single trace in external observability tools when they happen to execute on the same warm worker process. (#4534)
  • Task metrics no longer go missing for projects that configure their own metricExporters or metricReaders, and the flush error that came with it is fixed. (#4613)
  • idempotencyKeys.reset() now works when the idempotency key is exactly 64 characters long. Previously, any 64-character key was treated as already hashed, so passing one with a scope silently ignored the scope and the reset never found a match. (#4626)
  • Fair queue tenants can no longer get permanently stuck behind leaked concurrency slots. Slots are freed on every path that finishes a message, a failed release no longer causes a message to run twice or lose its retry, and a background sweep recovers any leaked slot so queues recover without manual cleanup. (#4540)

Server changes

These changes are included in the v4.5.12 Docker image and are already live on Trigger.dev Cloud:

  • Deployments and runs now display the external ID they were tagged or pinned with, so you can trace a run back to the specific release of your app. (#4665)
  • Operators can now route an organization's runs to specific Kubernetes node pools. (#4655)
  • Dashboard pages load faster on projects with many preview branches. (#4606)
  • Global log search now supports faster bounded substring matching and clearer time-range expansion. (#4615)
  • Task triggering is now more resilient to brief, transient service interruptions. (#4623)
  • Failed AI SDK tool call and embedding spans now show the error message and stack trace in the run inspector. (#4653)
  • Archiving a branch now returns you to the same page of the branches list, preserving your search and filters. (#4724)
  • Using * as a concurrency key no longer stalls the entire queue. Previously, a single run with that key could block all other runs on the queue until something else was triggered. (#4628)
  • Fixed a window after promoting or rolling back a deployment where newly triggered runs could still execute on the previous version. New runs now pick up the current version immediately. (#4622)
  • Root API keys no longer show an environment creation timestamp as their creation date. (#4612)
  • The app version shown on the organization settings page now reports the real version instead of v0.0.0. (#4611)
  • A paused environment now stays paused after a deploy. Previously a new deployment could restart execution on a paused environment. (#4625)
  • Alert webhook destinations in reserved benchmarking IP ranges are now rejected. (#4735)
  • TRQL queries using the PREWHERE clause are now rejected with a clear error. Use WHERE instead, which is filtered the same way but preserves data isolation guarantees. (#4735)
  • Run trace rows now respond consistently to mouse and keyboard selection, including Alt-click expansion controls. (#4701)
  • The "Back to app" button in organization settings now returns you to that specific organization instead of your most recently visited one. (#4632)
  • Runs triggered with a ttl that were requeued after a failure once their TTL had elapsed could get permanently stuck in the queued state. Requeued runs now dequeue normally: a run's TTL only applies while it's waiting to start for the first time. (#4669)

How to upgrade

Update the trigger.dev/* packages to v4.5.12 using your package manager:


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 # bun

Self-hosted users: update your Docker image to ghcr.io/triggerdotdev/trigger.dev:v4.5.12.

Ready to start building?

Build and deploy your first task in 3 minutes.

Get started now