releases.shpreview
Home/Trigger.dev
Trigger.dev

Trigger.dev

Trigger.dev Cloud now meets HIPAA Business Associate requirements. Sign a BAA and run workloads that process Protected Health Information on our managed infrastructure.

HIPAA (Health Insurance Portability and Accountability Act) governs how Protected Health Information (PHI) must be handled. Vendors that process PHI on behalf of covered entities (such as hospitals or insurers) act as Business Associates and must have a signed Business Associate Agreement (BAA) in place.

Signing a BAA

If your tasks process PHI, you'll need a signed BAA with Trigger.dev. Once the agreement is in place, you'll be migrated onto HIPAA infrastructure. This is a paid add-on — reach out via their contact form for HIPAA requests.

Security & Compliance

Trigger.dev maintains SOC 2 Type II certification and GDPR compliance. Full details are available on their security page and Security Portal.

Trigger.dev · v4.4.6

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

Self-hosted Docker image: ghcr.io/triggerdotdev/trigger.dev:v4.4.6

Release notes

Read the full release notes: https://trigger.dev/changelog/v4-4-6

What's changed

Improvements

  • Fail attempts on uncaught exceptions instead of hanging to MAX_DURATION_EXCEEDED. A Node EventEmitter (e.g. node-redis) emitting "error" with no .on("error", ...) listener escalates to uncaughtException, which the worker previously reported but did not act on — runs drifted to maxDuration with empty attempts. They now fail fast with the original error and status FAILED, and respect the task's normal retry policy. You should still attach .on("error", ...) listeners to long-lived clients to handle errors gracefully. (#3529)

Bug fixes

  • Fix dev workers spinning at 100% CPU after the parent CLI disconnects. Orphaned trigger-dev-run-worker (and indexer) processes were caught in an uncaughtException feedback loop: a periodic IPC send via process.send would throw ERR_IPC_CHANNEL_CLOSED once the parent closed the channel, which re-entered the same handler that itself called process.send, scheduled via setImmediate and amplified by source-map-support's prepareStackTrace. Fixed by (1) silently dropping packets in ZodIpcConnection when the channel is disconnected, (2) adding a process.on("disconnect", ...) handler in dev workers so they exit cleanly when the CLI closes the IPC channel, and (3) wrapping all uncaughtException-path process.send calls in a safeSend guard that checks process.connected and swallows synchronous throws. (#3491)

All packages: v4.4.6

@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, James Ritchie, @isshaddad, @d-cs, github-actions[bot], Matt Aitken, Saadi Myftija, Oskar Otwinowski

Full changelog: https://github.com/triggerdotdev/trigger.dev/compare/v4.4.5...v4.4.6

Faster failure on uncaught exceptions and a fix for dev workers spinning at 100% CPU.

1 improvement and 1 bug fix.

Improvements

  • Fail attempts on uncaught exceptions instead of hanging to MAX_DURATION_EXCEEDED. A Node EventEmitter (e.g. node-redis) emitting "error" with no .on("error", ...) listener escalates to uncaughtException, which the worker previously reported but did not act on: runs drifted to maxDuration with empty attempts. They now fail fast with the original error and status FAILED, and respect the task's normal retry policy. You should still attach .on("error", ...) listeners to long-lived clients to handle errors gracefully. (#3529)

Bug Fixes

  • Fix dev workers spinning at 100% CPU after the parent CLI disconnects. Orphaned trigger-dev-run-worker (and indexer) processes were caught in an uncaughtException feedback loop: a periodic IPC send via process.send would throw ERR_IPC_CHANNEL_CLOSED once the parent closed the channel, which re-entered the same handler via setImmediate, amplified by source-map-support's prepareStackTrace. Fixed by silently dropping packets in ZodIpcConnection when the channel is disconnected, adding a process.on("disconnect", ...) handler in dev workers so they exit cleanly, and wrapping all uncaughtException-path process.send calls in a safeSend guard. (#3491)

How to Upgrade

Update the trigger.dev/* packages to v4.4.6 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.4.6.

Trigger.dev · v4.4.5

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

Self-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-browser flag to init and login to skip auto-opening the browser during authentication. Also error loudly when init is run without --yes under non-TTY stdin (previously default-and-exited silently, leaving the project half-initialized). Both commands now show an Examples section in --help. (#3483)
  • Add isReplay boolean to the run context (ctx.run.isReplay), derived from the existing replayedFromTaskRunFriendlyId database field. Defaults to false for backwards compatibility. (#3454)
  • Redact the resolveWaitpoint runtime log so it only emits id and type instead of the full completed waitpoint. Previously the log printed the entire waitpoint (including output) to stdout in production runs, which could leak sensitive payloads. The value returned by wait.forToken() is unchanged. (#3490)
  • Add SessionId friendly ID generator and schemas for the new durable Session primitive. Exported from @trigger.dev/core/v3/isomorphic alongside RunId, BatchId, etc. Ships the CreateSessionStreamWaitpoint request/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 /admin and 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 a tokenBucket override (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_POLICY env 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, default small-1x). Use COMPUTE_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 RevokedApiKey table with a 24 hour grace window, and findEnvironmentByApiKey falls back to it when the submitted key doesn't match any live environment. The grace window can be ended early (or extended) by updating expiresAt on the row. (#3420)

  • Add the Session primitive — a durable, task-bound, bidirectional I/O channel that outlives a single run and acts as the run manager for chat.agent. Ships the Postgres Session + SessionRun tables, ClickHouse sessions_v1 + replication service, the sessions JWT scope, and the public CRUD + realtime routes (/api/v1/sessions, /realtime/v1/sessions/:session/:io) including end-and-continue for server-orchestrated run handoffs and session-stream waitpoints. (#3417)

  • Add KUBERNETES_POD_DNS_NDOTS_OVERRIDE_ENABLED flag (off by default) that overrides the cluster default and sets dnsConfig.options.ndots on runner pods (defaulting to 2, configurable via KUBERNETES_POD_DNS_NDOTS). Kubernetes defaults pods to ndots: 5, so any name with fewer than 5 dots — including typical external domains like api.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 lower ndots value reduces DNS query amplification in the cluster.local zone.

    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 getEntitlement in platform.v3.server.ts. Eliminates a synchronous billing-service HTTP round trip on every trigger. Reuses the existing platformCache (LRU memory + Redis) pattern already used for limits and usage. 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 MicroVM badge 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 so NODE_MAX_OLD_SPACE_SIZE can 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 all prisma:engine:* spans (including prisma:engine:connection used by the connection-pool monitors) and the outer prisma:client:operation span. (#3422)

  • Clarify the cross-region intent in the Terraform and AI-prompt helpers on the Add Private Connection page. Both already default supported_regions to ["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_ENABLED flag (default off) to route the Prisma reads inside RunEngine.getSnapshotsSince through 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) on TaskSchedule and TaskScheduleInstance. 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 associated IO:XactSync mini-spikes on the writer. Customer-facing payload.lastTimestamp semantics 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. validatePublicJwtKey falls back to any non-expired RevokedApiKey rows for the signing environment when the primary signature check against the env's current apiKey fails. 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 DEQUEUED status. DEQUEUED was missing from NON_FINAL_RUN_STATUSES so 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 in handleDebounce so 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/:id called fetch() 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. Thread getRequestAbortSignal() through RealtimeClient.streamRun/streamRuns/streamBatch to longPollingFetch and 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() in sse.ts retaining its source signals indefinitely (see nodejs/node#54614, nodejs/node#55351). Also clear the setTimeout(abort) timer in entry.server.tsx so 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 next URL 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: https://github.com/triggerdotdev/trigger.dev/compare/v4.4.4...v4.4.5

Run replay detection with ctx.run.isReplay, a --no-browser CLI flag for headless environments, and a 24-hour grace window for API key rotations.

3 improvements and 12 server changes.

Highlights

ctx.run.isReplay

Tasks can now check whether the current run is a replay via ctx.run.isReplay, allowing you to skip side effects like email sends or payments during replays.

export const myTask = task({
  id: "my-task",
  run: async (payload, { ctx }) => {
    if (ctx.run.isReplay) {
      // Skip side effects like sending emails or charging cards on replay
      return;
    }
    await sendEmail(payload.to);
  },
});

Improvements

  • --no-browser CLI flag: Add --no-browser flag to init and login to skip auto-opening the browser during authentication. Useful for CI and headless environments. Also errors loudly when init is run without --yes under non-TTY stdin, instead of silently half-initializing the project. Both commands now include an Examples section in --help.
  • Stack trace truncation: Truncate large error stacks and messages to prevent OOM crashes: stack traces capped at 50 frames (top 5 + bottom 45 with an omission notice), individual lines at 1024 chars, and error messages at 1000 chars. Applied in parseError, sanitizeError, and OTel span recording.

Server Changes

Changes included in the v4.4.5 Docker image and live on Trigger.dev Cloud:

  • Add a server-side deprecation gate for deploys from v3 CLI versions, controlled by the DEPRECATE_V3_CLI_DEPLOYS_ENABLED env var. v4 CLI deploys are unaffected.
  • Regenerating an environment API key no longer invalidates the previous key immediately. The old key gets a 24-hour grace window via a new RevokedApiKey table, and PATs signed with the rotated key also remain valid during that window.
  • Ship the Errors page to all users, with Slack alert improvements (viewer-timezone timestamps via <!date^> token, pinned "No channel" picker item), activity sparkline peak tooltips, and several dashboard UI fixes.
  • Session primitive server infrastructure: Postgres Session + SessionRun tables, ClickHouse sessions_v1 + replication, the sessions JWT scope, and CRUD + realtime routes including end-and-continue for server-orchestrated run handoffs.
  • Increase the default maximum project count per organization from 10 to 25.
  • Replace the DISTINCT query for task filter dropdowns with a dedicated TaskIdentifier registry table backed by Redis. Fixes duplicate entries when a task changes trigger source and adds active/archived grouping. Environments migrate automatically on their next deploy.
  • Stop writing per-tick state (lastScheduledTimestamp, nextScheduledTimestamp, lastRunTriggeredAt) on TaskSchedule. Customer-facing payload.lastTimestamp semantics are unchanged.
  • Batch items that hit the environment queue size limit now fast-fail without retries and without creating pre-failed TaskRuns.
  • Fix RSS memory leak in realtime proxy routes: thread getRequestAbortSignal() through RealtimeClient to cancel upstream Electric requests on client disconnect. Isolated reproducer showed ~44 KB retained per leaked request.
  • Fix memory leak where aborted SSE connections pinned the full request/response graph on Node 20, caused by AbortSignal.any() retaining source signals indefinitely. Also clears the setTimeout(abort) timer in entry.server.tsx so successful HTML renders don't retain the React tree for 30 seconds.
  • Fix Redis connection leak in realtime streams: non-blocking methods now share a single connection, and streaming connections tear down via disconnect() immediately with a 15-second inactivity fallback.
  • Upgrade Remix from 2.1.0 to 2.17.4 to address React Router security vulnerabilities.

How to Upgrade

Update trigger.dev packages to v4.4.5:

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: update your Docker image to ghcr.io/triggerdotdev/trigger.dev:v4.4.5.

Quickly track down what's causing your runs to fail with error alerts. Then bulk replay when you've shipped the fix.

The new Errors page collapses failed runs into groups. A bad deploy that fails 800 times sends 1 alert, not 800. Ship the fix, click bulk replay, and the count flattens as the runs succeed.

Fingerprinted error groups

Every failed run gets fingerprinted by its error class and message. Dynamic parts (IDs, UUIDs, timestamps) are stripped, so 200 instances of User abc-123 not found and User xyz-789 not found collapse into one row.

The group page shows the timeline, the runs that hit it, the task versions contributing, and the first / last seen timestamps. Click any run to jump into the run detail.

One alert per group

A new group, or one firing again after being resolved, sends a Slack message, email, or webhook. The payload has the message, the stack, and a link straight to the dashboard.

Alerts are configured per project under Alerts, scoped to specific tasks and environments.

Status: unresolved, resolved, ignored

Three states. Mark one resolved when you've shipped the fix. Ignore it for hours or days when you're not ready (revert anytime).

If a resolved group fires again, it flips back to unresolved and a fresh alert goes out.

Bulk actions let you triage many at once. Select 50 stale groups, mark them resolved, move on.

Bulk replay

Replay every run in a group from the group page. The replays stay attached to the original group, so the count drops as they succeed.

Useful for the obvious case (a deploy nuked 200 jobs, you shipped the fix, you want them all to re-run) and for the less obvious one: verifying the fix actually held. 200 runs failed, 200 replays succeed, the group quiets down, you know.

Filter by task version

The list and individual error page filter by task version. The chart on the individual page stacks errors by version, so you can pinpoint which deploy introduced a regression and which one fixed it.

Every postmortem starts with "which deploy introduced this?" The version chart answers it before you've finished asking.

Get started

Open Errors in the sidebar of any project. Configure alerts under Alerts.

Reach private databases, caches, and APIs from your tasks over AWS PrivateLink — no public endpoints, IP allowlists, or VPN required.

With AWS PrivateLink support, Trigger.dev tasks can connect directly to private AWS resources inside your VPC:

  • RDS (Postgres, MySQL, Aurora)
  • ElastiCache (Redis, Memcached)
  • Internal microservices and APIs
  • Self-hosted databases on EC2
  • Anything else reachable inside your VPC

How it works

  1. Create a Network Load Balancer and VPC Endpoint Service in your AWS account.
  2. Add Trigger.dev's account as an allowed principal.
  3. Provision a VPC Endpoint — Trigger.dev handles the rest.

Connections are isolated using a CiliumNetworkPolicy (eBPF kernel-level traffic filtering) targeting pods labeled with your org ID, so your private resources are only reachable from your own tasks.

Setup options

  • Enter an existing VPC Endpoint Service name
  • Generate a pre-filled Terraform script
  • Use an AI agent prompt to create resources automatically
  • Follow a step-by-step AWS Console walkthrough

All configured via Settings → Private Connections.

Availability

  • Plans: Pro and Enterprise
  • Default limit: 2 connections per organization
  • Regions: Available across 28 AWS regions on the customer side; consumed in us-east-1 and eu-central-1
  • Connections are organization-wide, accessible across all projects and environments

Bidirectional task communication — send typed data into running tasks from your backend or frontend, with four receiving patterns from suspending (frees compute) to non-blocking.

Requires SDK v4.4.2+: npm install @trigger.dev/sdk@latest @trigger.dev/react-hooks@latest

Four receiving patterns

.on(): listen in the background

Fires your handler every time data arrives. The task keeps running. Useful for cancel signals and agent steering.

cancelSignal.on((data) => {
  console.log("Cancelled:", data.reason);
  controller.abort();
});
.wait(): suspend until data arrives

The task process is freed entirely — no compute cost while you wait. Resumes at the exact stopping point when data arrives, like a typed waitpoint.

const result = await approval.wait({ timeout: "7d" });
if (result.ok && result.output.approved) {
  await publish(draft);
}
.once(): block for the next message

Blocks for the next message while keeping the process alive.

const data = await approval.once({ timeoutMs: 300_000 }).unwrap();
.peek(): check without waiting

Non-blocking. Returns the latest buffered value, or undefined if nothing has arrived yet.

const latest = cancelSignal.peek();
if (latest) {
  // Someone already sent a cancel before we checked
}

Send from your backend

await userMessage.send(runId, {
  type: "follow-up",
  text: "Focus on competitor pricing",
});

Send from your frontend

Use the useInputStreamSend React hook with full type safety.

"use client";
import { useInputStreamSend } from "@trigger.dev/react-hooks";
import { userMessage } from "@/trigger/streams";

export function ResearchChat({ runId, accessToken }: {
  runId: string;
  accessToken: string;
}) {
  const { send, isReady } = useInputStreamSend(
    userMessage.id, runId, { accessToken }
  );

  return (
    <div>
      <button disabled={!isReady}
        onClick={() => send({ type: "follow-up", text: "Go deeper on the pricing model" })}>
        Go deeper
      </button>
      <button disabled={!isReady}
        onClick={() => send({ type: "wrap-up", text: "That's enough, compile the report" })}>
        Wrap up
      </button>
    </div>
  );
}

Get started

Define a typed stream:

// trigger/streams.ts
import { streams } from "@trigger.dev/sdk";

export const userMessage = streams.input<{
  type: "instruction" | "follow-up" | "wrap-up";
  text: string;
}>({ id: "user-message" });

Listen in your task:

// trigger/research.ts
import { task } from "@trigger.dev/sdk";
import { userMessage } from "./streams";

export const researchAgent = task({
  id: "research-agent",
  run: async (payload: { topic: string }) => {
    const messages: string[] = [];
    let shouldWrapUp = false;

    userMessage.on((data) => {
      if (data.type === "wrap-up") {
        shouldWrapUp = true;
      }
      messages.push(data.text);
    });

    let context = payload.topic;
    while (!shouldWrapUp) {
      const result = await generateResearch(context);
      await saveFindings(result);
      if (messages.length > 0) {
        context = `${context}\n\nUser feedback:\n${messages.splice(0).join("\n")}`;
      }
    }
    return await compileFinalReport(context);
  },
});
Trigger.dev · v4.4.4

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

Self-hosted Docker image: ghcr.io/triggerdotdev/trigger.dev:v4.4.4

Release notes

Read the full release notes: https://trigger.dev/changelog/v4-4-4

What's changed

Highlights

  • Add support for setting TTL (time-to-live) defaults at the task level and globally in trigger.config.ts, with per-trigger overrides still taking precedence (#3196)
  • Large run outputs can use the new API which allows switching object storage providers. (#3275)

CLI Improvements

  • Add platform notifications support to the CLI. The trigger dev and trigger login commands now fetch and display platform notifications (info, warn, error, success) from the server. Includes discovery-based filtering to conditionally show notifications based on project file patterns, color markup rendering for styled terminal output, and a non-blocking display flow with a spinner fallback for slow fetches. Use --skip-platform-notifications flag with trigger dev to disable the notification check. (#3254)

MCP Server improvements

  • Add get_span_details MCP tool for inspecting individual spans within a run trace. (#3255)
  • Span IDs now shown in get_run_details trace output for easy discovery
  • New API endpoint GET /api/v1/runs/:runId/spans/:spanId
  • get_query_schema — discover available TRQL tables and columns
  • query — execute TRQL queries against your data
  • list_dashboards — list built-in dashboards and their widgets
  • run_dashboard_query — execute a single dashboard widget query
  • whoami — show current profile, user, and API URL
  • list_profiles — list all configured CLI profiles
  • switch_profile — switch active profile for the MCP session
  • start_dev_server — start trigger dev in the background and stream output
  • stop_dev_server — stop the running dev server
  • dev_server_status — check dev server status and view recent logs
  • GET /api/v1/query/schema — query table schema discovery
  • GET /api/v1/query/dashboards — list built-in dashboards
  • --readonly flag hides write tools (deploy, trigger_task, cancel_run) so the AI cannot make changes
  • read:query JWT scope for query endpoint authorization
  • get_run_details trace output is now paginated with cursor support
  • MCP tool annotations (readOnlyHint, destructiveHint) for all tools
  • get_query_schema now requires a table name and returns only one table's schema (was returning all tables)
  • get_current_worker no longer inlines payload schemas; use new get_task_schema tool instead
  • Query results formatted as text tables instead of JSON (~50% fewer tokens)
  • cancel_run, list_deploys, list_preview_branches formatted as text instead of raw JSON
  • Schema and dashboard API responses cached to avoid redundant fetches
  • Adapted the CLI API client to propagate the trigger source via http headers. (#3241)
  • --readonly flag hides write tools (deploy, trigger_task, cancel_run) so the AI cannot make changes
  • get_run_details trace output is now paginated with cursor support
  • MCP tool annotations (readOnlyHint, destructiveHint) for all tools
  • get_query_schema now requires a table name and returns only one table's schema (was returning all tables)
  • get_current_worker no longer inlines payload schemas; use new get_task_schema tool instead
  • Query results formatted as text tables instead of JSON (~50% fewer tokens)
  • cancel_run, list_deploys, list_preview_branches formatted as text instead of raw JSON
  • Schema and dashboard API responses cached to avoid redundant fetches

Bug fixes

  • Fix dev CLI leaking build directories on rebuild, causing disk space accumulation. Deprecated workers are now pruned (capped at 2 retained) when no active runs reference them. The watchdog process also cleans up .trigger/tmp/ when the dev CLI is killed ungracefully (e.g. SIGKILL from pnpm). (#3224)
  • Fix --load flag being silently ignored on local/self-hosted builds. (#3114)
  • Fixed search_docs tool failing due to renamed upstream Mintlify tool (SearchTriggerDevsearch_trigger_dev)
  • Fixed list_deploys failing when deployments have null runtime/runtimeVersion fields (#3139)
  • Fixed list_preview_branches crashing due to incorrect response shape access
  • Fixed metrics table column documented as value instead of metric_value in query docs
  • Fixed dev CLI leaking build directories on rebuild — deprecated workers now clean up their build dirs when their last run completes
  • Fixed search_docs tool failing due to renamed upstream Mintlify tool (SearchTriggerDevsearch_trigger_dev)
  • Fixed list_deploys failing when deployments have null runtime/runtimeVersion fields (#3139)
  • Fixed list_preview_branches crashing due to incorrect response shape access
  • Fixed metrics table column documented as value instead of metric_value in query docs
  • Fixed dev CLI leaking build directories on rebuild — deprecated workers now clean up their build dirs when their last run completes

Server changes

These changes affect the self-hosted Docker image and Trigger.dev Cloud:

  • Add admin UI for viewing and editing feature flags (org-level overrides and global defaults). (#3291)

Other improvements:

  • Add allowRollbacks query param to the promote deployment API to enable version downgrades (#3214)

  • Add automatic LLM cost calculation for spans with GenAI semantic conventions. When a span arrives with gen_ai.response.model and token usage data, costs are calculated from an in-memory pricing registry backed by Postgres and dual-written to both span attributes (trigger.llm.*) and a new llm_metrics_v1 ClickHouse table that captures usage, cost, performance (TTFC, tokens/sec), and behavioral (finish reason, operation type) metrics. (#3213)

  • Add API endpoint GET /api/v1/runs/:runId/spans/:spanId that returns detailed span information including properties, events, AI enrichment (model, tokens, cost), and triggered child runs. (#3255)

  • Multi-provider object storage with protocol-based routing for zero-downtime migration (#3275)

  • Add IAM role-based auth support for object stores (no access keys required). (#3275)

  • Add platform notifications to inform users about new features, changelogs, and platform events directly in the dashboard. (#3254)

  • Add private networking support via AWS PrivateLink. Includes BillingClient methods for managing private connections, org settings UI pages for connection management, and supervisor changes to apply privatelink pod labels for CiliumNetworkPolicy matching. (#3264)

  • Reduce run start latency by skipping the intermediate queue when concurrency is available. This optimization is rolled out per-region and enabled automatically for development environments. (#3299)

  • Extended the search filter on the environment variables page to match on environment type (production, staging, development, preview) and branch name, not just variable name and value. (#3302)

  • Set application_name on Prisma connections from SERVICE_NAME so DB load can be attributed by service (#3348)

  • Fix transient R2/object store upload failures during batchTrigger() item streaming.

    • Added p-retry (3 attempts, 500ms–2s exponential backoff) around uploadPacketToObjectStore in BatchPayloadProcessor.process() so transient network errors self-heal server-side rather than aborting the entire batch stream.
    • Removed x-should-retry: false from the 500 response on the batch items route so the SDK's existing 5xx retry path can recover if server-side retries are exhausted. Item deduplication by index makes full-stream retries safe. (#3331)
  • Concurrency-keyed queues now use a single master queue entry per base queue instead of one entry per key. Prevents high-CK-count tenants from consuming the entire parentQueueLimit window and starving other tenants on the same shard. (#3219)

  • Reduce lock contention when processing large batchTriggerAndWait batches. Previously, each batch item acquired a Redis lock on the parent run to insert a TaskRunWaitpoint row, causing LockAcquisitionTimeoutError with high concurrency (880 errors/24h in prod). Since blockRunWithCreatedBatch already transitions the parent to EXECUTING_WITH_WAITPOINTS before items are processed, the per-item lock is unnecessary. The new blockRunWithWaitpointLockless method performs only the idempotent CTE insert without acquiring the lock. (#3232)

  • Strip secure query parameter from QUERY_CLICKHOUSE_URL before passing to ClickHouse client. This was already done for the main and logs ClickHouse clients but was missing for the query client, causing a startup crash with Error: Unknown URL parameters: secure. (#3204)

  • Fix OrganizationsPresenter.#getEnvironment matching the wrong development environment on teams with multiple members. All dev environments share the slug "dev", so the previous find by slug alone could return another member's environment. Now filters DEVELOPMENT environments by orgMember.userId to ensure the logged-in user's dev environment is selected. (#3273)

All packages: v4.4.4

@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, Oskar Otwinowski, Matt Aitken, James Ritchie, @nicktrn, Saadi Myftija, @D-K-P, @isshaddad, github-actions[bot], @chengzp, Dinko Osrecki

Full changelog: https://github.com/triggerdotdev/trigger.dev/compare/v4.4.3...v4.4.4

2 new features, 11 new MCP tools, 6 bug fixes, and 15 server changes.

Highlights

Task-level and global TTL defaults

You can now set TTL (time-to-live) defaults at the task level in your task definition and globally in trigger.config.ts. If a run isn't dequeued within the configured window, it expires and never executes. Per-trigger overrides still take precedence over both.

// trigger.config.ts — set a project-wide default
import { defineConfig } from "@trigger.dev/sdk";

export default defineConfig({
  project: "<project ref>",
  ttl: "1h", // runs expire after 1 hour if not dequeued
});
// task — override the global default for this task
export const myTask = task({
  id: "my-task",
  ttl: "30m", // this task's runs expire after 30 minutes
  run: async (payload) => {
    // ...
  },
});

Set ttl: 0 on a task to opt out of the global default entirely.

Multi-provider object storage for large run outputs

Large run outputs now use a new storage API that supports switching object storage providers with zero-downtime migration via protocol-based routing. IAM role-based authentication is also supported, eliminating the need for access keys.

CLI improvements

  • Platform notifications: the trigger dev and trigger login commands now fetch and display notifications (info, warn, error, success) from the server with color markup rendering. Discovery-based filtering shows notifications based on your project file patterns. Use --skip-platform-notifications to disable.

MCP server improvements

New tools
  • get_span_details — inspect individual spans within a run trace, including attributes, timing, events, and AI enrichment (model, tokens, cost). Span IDs are now shown in get_run_details trace output for easy discovery.
  • get_query_schema — discover available TRQL tables and columns
  • query — execute TRQL queries against your data
  • list_dashboards — list built-in dashboards and their widgets
  • run_dashboard_query — execute a single dashboard widget query
  • whoami — show current profile, user, and API URL
  • list_profiles — list all configured CLI profiles
  • switch_profile — switch the active profile for the MCP session
  • start_dev_server — start trigger dev in the background and stream output
  • stop_dev_server — stop the running dev server
  • dev_server_status — check dev server status and view recent logs
Improvements
  • --readonly flag hides write tools (deploy, trigger_task, cancel_run) so the AI cannot make changes
  • get_run_details trace output is now paginated with cursor support
  • get_query_schema now requires a table name and returns only that table's schema
  • get_current_worker no longer inlines payload schemas — use the new get_task_schema tool instead
  • Query results formatted as text tables instead of JSON (~50% fewer tokens)
  • cancel_run, list_deploys, list_preview_branches formatted as text instead of raw JSON
  • Schema and dashboard API responses cached to avoid redundant fetches
  • MCP tool annotations (readOnlyHint, destructiveHint) added to all tools
  • read:query JWT scope added for query endpoint authorization
  • CLI API client now propagates the trigger source via HTTP headers

Bug fixes

  • Fix dev CLI leaking build directories on rebuild. Deprecated workers are now pruned (capped at 2 retained) when no active runs reference them.
  • Fix --load flag being silently ignored on local and self-hosted builds.
  • Fixed search_docs MCP tool failing due to a renamed upstream Mintlify tool (SearchTriggerDevsearch_trigger_dev).
  • Fixed list_deploys MCP tool failing when deployments have null runtime or runtimeVersion fields.
  • Fixed list_preview_branches MCP tool crashing due to incorrect response shape access.
  • Fixed metrics TRQL table column documented as value instead of metric_value.

Server changes

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

  • Add admin UI for viewing and editing feature flags with org-level overrides and global defaults.
  • Add allowRollbacks query param to the promote deployment API to support version downgrades.
  • Automatic LLM cost calculation for spans with GenAI semantic conventions. Costs are calculated from an in-memory pricing registry and written to span attributes.
  • New GET /api/v1/runs/:runId/spans/:spanId endpoint returning span properties, events, AI enrichment, and triggered child runs.
  • Multi-provider object storage with protocol-based routing for zero-downtime migration. Adds IAM role-based auth for object stores (no access keys required).
  • Platform notifications for informing users about new features and platform events directly in the CLI and dashboard.
  • Private networking support via AWS PrivateLink. Includes BillingClient methods for managing connections, org settings UI for connection management, and supervisor pod labels for CiliumNetworkPolicy matching.
  • Reduce run start latency by skipping the intermediate queue when concurrency is available, rolled out per-region and enabled automatically for development environments.
  • Environment variable page search now matches on environment type (production, staging, development, preview) and branch name, not just variable name and value.
  • Set application_name on Prisma connections from SERVICE_NAME for DB load attribution by service.
  • Add p-retry (3 attempts, 500ms–2s exponential backoff) around object store uploads in BatchPayloadProcessor.
  • Concurrency-keyed queues now use a single master queue entry per base queue instead of one per key, preventing high-CK-count tenants from starving others on the same shard.
  • Reduce lock contention when processing large batchTriggerAndWait batches by removing the per-item Redis lock acquisition.
  • Strip secure query parameter from QUERY_CLICKHOUSE_URL before passing to the ClickHouse client, fixing a startup crash with Error: Unknown URL parameters: secure.
  • Fix dev environment selection for teams with multiple members: now filters DEVELOPMENT environments by orgMember.userId to ensure the logged-in user's dev environment is returned.

How to upgrade

Update the trigger.dev/* packages to v4.4.4 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.4.4.

Trigger.dev · v4.4.3

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

Self-hosted Docker image: ghcr.io/triggerdotdev/trigger.dev:v4.4.3

Release notes

Read the full release notes: https://trigger.dev/changelog/v4-4-3

What's changed

Improvements

  • Add syncSupabaseEnvVars to pull database connection strings and save them as trigger.dev environment variables (#3152)
  • Auto-cancel in-flight dev runs when the CLI exits, using a detached watchdog process that survives pnpm SIGKILL (#3191)

Server changes

These changes affect the self-hosted Docker image and Trigger.dev Cloud:

  • A new Errors page for viewing and tracking errors that cause runs to fail

    • Errors are grouped using error fingerprinting
    • View top errors for a time period, filter by task, or search the text
    • View occurrences over time
    • View all the runs for an error and bulk replay them (#3172)
  • Add sidebar tabs (Options, AI, Schema) to the Test page for schemaTask payload generation and schema viewing. (#3188)

All packages: v4.4.3

@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, Matt Aitken, James Ritchie, Oskar Otwinowski

Full changelog: https://github.com/triggerdotdev/trigger.dev/compare/v4.4.2...v4.4.3

Connect your Vercel project to Trigger.dev and never run a manual deploy command again. Automatic deploys, env var sync, and atomic deployments.

What it does

Three things, all automatic:

  1. Automatic deployments: Push code, Vercel deploys your app, Trigger.dev deploys your tasks. No trigger.dev deploy command, no CI/CD config to maintain.
  2. Environment variable sync: Variables flow both ways. Your Vercel env vars get pulled into Trigger.dev before each build. Trigger.dev syncs API keys (like TRIGGER_SECRET_KEY) back to Vercel.
  3. Atomic deployments: Your Vercel app and Trigger.dev tasks deploy in lockstep. Your app never goes live with a mismatched task version.

Atomic deployments

When atomic deployments are enabled, Trigger.dev gates your Vercel deployment until the task build completes, sets the correct TRIGGER_VERSION, then triggers a Vercel redeployment.

Environment mapping

Vercel environmentTrigger.dev environment
ProductionProduction
Custom environmentStaging
PreviewPreview
DevelopmentDevelopment

Environment variable sync

Sync happens in both directions between Vercel and Trigger.dev per-environment.

Build options

  • Atomic deployments: Sync Vercel and Trigger.dev deployments
  • Pull env vars before build: Retrieve latest Vercel env vars before each build
  • Discover new env vars: Auto-create new Trigger.dev vars when they appear in Vercel

Getting started

Connect from Trigger.dev Settings or the Vercel Marketplace. Deploy the Next.js starter app with one click.

Error tracking dashboard, Supabase environment variable sync, and dev run auto-cancel on CLI exit.

Improvements

  1. syncSupabaseEnvVars automates Supabase connection string integration into environment variables. The feature retrieves database credentials and eliminates manual configuration steps for Supabase-connected tasks. (docs, #3152)
// trigger.config.ts
import { defineConfig } from "@trigger.dev/sdk";
import { syncSupabaseEnvVars } from "@trigger.dev/build/extensions/core";

export default defineConfig({
  build: {
    extensions: [syncSupabaseEnvVars()],
  },
});
  1. Auto-cancel in-flight dev runs when CLI terminates, using a detached watchdog process that survives pnpm SIGKILL. (#3191)

Server Changes

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

  1. New Errors page for viewing and tracking run failures. Errors are grouped by fingerprint — view top errors for a time period, filter by task, search by text, and see occurrences over time. Users can list affected runs and bulk replay them from the error detail view. (#3172)

    Private alpha on Trigger.dev Cloud — The Errors page is available now for self-hosted users. On Trigger.dev Cloud it's currently in private alpha, with a full public release coming soon.

  2. Test page AI payload generation automatically creates example payloads using AI. For schemaTask tasks, the AI uses your task's JSON schema to generate valid payloads. New sidebar tabs provide visibility into Options, AI, and Schema. (#3188)

How to Upgrade

Update the trigger.dev/* packages to v4.4.3 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.4.3.

Trigger.dev has launched Query & Dashboards, enabling users to analyze task data using SQL-style queries or custom dashboards with visualizations.

TRQL Query Language

  • SQL-style language compiling to ClickHouse for analytical queries
  • Two queryable tables: runs (status, timing, costs, machine type, tags, metadata) and metrics (CPU, memory, custom OpenTelemetry metrics)
  • Built-in functions: timeBucket() for time-series aggregation, quantile() for percentiles

AI-Powered Query Assistant

  • Natural language query generation — describe desired data in plain English
  • Automatic error detection with "Try fix error" suggestions
  • Schema-aware responses handling cost analysis, error breakdowns, and duration percentiles

Pre-Built Dashboard

Automatic project dashboard covering: run volume, success rates, failure analysis, costs (by task/machine), and deployment version metrics.

Custom Dashboard Widgets

  • Big Numbers: Single-value KPIs with customizable formatting (abbreviations, prefixes/suffixes)
  • Charts: Bar, stacked bar, line, and area charts with automatic zero-filling and intelligent time bucketing
  • Tables: Sortable, detailed breakdowns with column reordering and filtering
  • Layout: Drag-and-drop arrangement on 12-column grid, auto-saving

Real-Time Filtering

  • Time (presets + custom ranges), task selection, queue filtering, scope (environment/project/organization)
  • Applied simultaneously across all dashboard widgets
  • Auto-refresh every 60 seconds

SDK & API Integration

  • query.execute() function for type-safe queries with QueryTable autocomplete
  • REST API endpoint for custom views, monitoring tool integration, and AI agent debugging
Trigger.dev · v4.4.2

Upgrade

npx trigger.dev@latest update
pnpm dlx trigger.dev@latest update
yarn dlx trigger.dev@latest update
bunx trigger.dev@latest update 

Self-hosted Docker image: ghcr.io/triggerdotdev/trigger.dev:v4.4.2

Release notes

Read the full release notes: https://trigger.dev/changelog/v4-4-2

What's changed

Improvements

  • Add input streams for bidirectional communication with running tasks. Define typed input streams with streams.input<T>({ id }), then consume inside tasks via .wait() (suspends the process), .once() (waits for next message), or .on() (subscribes to a continuous stream). Send data from backends with .send(runId, data) or from frontends with the new useInputStreamSend React hook. (#3146)
  • Add PAYLOAD_TOO_LARGE error to handle graceful recovery of sending batch trigger items with payloads that exceed the maximum payload size (#3137)

Bug fixes

  • Fix slow batch queue processing by removing spurious cooloff on concurrency blocks and fixing a race condition where retry attempt counts were not atomically updated during message re-queue. (#3079)
  • fix(sdk): batch triggerAndWait variants now return correct run.taskIdentifier instead of unknown (#3080)

Server changes

These changes affect the self-hosted Docker image and Trigger.dev Cloud:

  • Two-level tenant dispatch architecture for batch queue processing. Replaces the single master queue with a two-level index: a dispatch index (tenant → shard) and per-tenant queue indexes (tenant → queues). This enables O(1) tenant selection and fair scheduling across tenants regardless of queue count. Improves batch queue processing performance. (#3133)

  • Add input streams with API routes for sending data to running tasks, SSE reading, and waitpoint creation. Includes Redis cache for fast .send() to .wait() bridging, dashboard span support for input stream operations, and s2-lite support with configurable S2 endpoint, access token skipping, and S2-Basin headers for self-hosted deployments. Adds s2-lite to Docker Compose for local development. (#3146)

  • Speed up batch queue processing by disabling cooloff and increasing the batch queue processing concurrency limits on the cloud:

    • Pro plan: increase to 50 from 10.
    • Hobby plan: increase to 10 from 5.
    • Free plan: increase to 5 from 1. (#3079)
  • Move batch queue global rate limiter from FairQueue claim phase to BatchQueue worker queue consumer for accurate per-item rate limiting. Add worker queue depth cap to prevent unbounded growth that could cause visibility timeouts. (#3166)

  • Fix a race condition in the waitpoint system where a run could be blocked by a completed waitpoint but never be resumed because of a PostgreSQL MVCC issue. This was most likely to occur when creating a waitpoint via wait.forToken() at the same moment as completing the token with wait.completeToken(). Other types of waitpoints (timed, child runs) were not affected. (#3075)

  • Fix metrics dashboard chart series colors going out of sync and widgets not reloading stale data when scrolled back into view (#3126)

  • Gracefully handle oversized batch items instead of aborting the stream.

    When an NDJSON batch item exceeds the maximum size, the parser now emits an error marker instead of throwing, allowing the batch to seal normally. The oversized item becomes a pre-failed run with PAYLOAD_TOO_LARGE error code, while other items in the batch process successfully. This prevents batchTriggerAndWait from seeing connection errors and retrying with exponential backoff.

    Also fixes the NDJSON parser not consuming the remainder of an oversized line split across multiple chunks, which caused "Invalid JSON" errors on subsequent lines. (#3137)

  • Require the user is an admin during an impersonation session. Previously only the impersonation cookie was checked; now the real user's admin flag is verified on every request. If admin has been revoked, the session falls back to the real user's ID. (#3078)

All packages: v4.4.2

@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

Full changelog: https://github.com/triggerdotdev/trigger.dev/compare/v4.4.1...v4.4.2

Input streams for bidirectional task communication, batch queue performance improvements, and security hardening.

1 new feature, 2 improvements, 2 bug fixes, and 7 server changes.

Input Streams for Bidirectional Communication with Running Tasks

Tasks now support typed input streams for receiving data during execution, including the ability to suspend tasks while awaiting responses.

// streams.ts — define once, share everywhere
import { streams } from "@trigger.dev/sdk";

export const approval = streams.input<{ approved: boolean; reviewer: string }>({
  id: "approval",
});
// task — suspend until a reviewer responds (frees compute while waiting)
const result = await approval.wait({ timeout: "7d" });
if (result.ok && result.output.approved) {
  await publish(draft);
}
// backend — send data to the running task
await approval.send(runId, { approved: true, reviewer: "alice@example.com" });

Additional capabilities include .once() for non-suspending waits, .on() for persistent listeners (useful for cancel signals on AI tasks), and a useInputStreamSend React hook for frontend integration. (#3146)

Improvements

  • Increased Batch trigger processing concurrency limits: Free plan 1 → 5, Hobby plan stays at 10, Pro plan 10 → 50. (#3079)
  • Added PAYLOAD_TOO_LARGE error code for oversized batch trigger items to fail gracefully with pre-failed runs instead of aborting entire batches. (#3137)

Bug Fixes

  • Fixed slow batch queue processing caused by spurious cooloff on concurrency blocks and race condition with non-atomic retry attempt count updates during message re-queue. (#3079)
  • Fixed batchTriggerAndWait variants returning unknown for run.taskIdentifier instead of correct values. (#3080)

Server Changes

Available in v4.4.2 Docker image and live on Trigger.dev Cloud:

  • Two-level tenant dispatch replacing single master queue with two-level index for O(1) tenant selection and fair scheduling. (#3133)
  • Server-side input streams support: API routes, SSE reading, waitpoint creation, and Redis caching for .send()-to-.wait() bridging. Includes dashboard span support and s2-lite support. (#3146)
  • Batch queue processing concurrency limits increased with disabled cooloff. (#3079)
  • Batch queue global rate limiter moved to per-item limiting with worker queue depth cap. (#3166)
  • Fixed waitpoint race condition where runs could be blocked indefinitely due to PostgreSQL MVCC issue. (#3075)
  • Oversized NDJSON batch items now emit as pre-failed runs with PAYLOAD_TOO_LARGE. (#3137)
  • Impersonation sessions now verify real user admin status on every request. (#3078)

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

Self-hosted: Update Docker image to ghcr.io/triggerdotdev/trigger.dev:v4.4.2.