Workflow SDK vs trigger.dev

trigger.dev is an open-source, TypeScript-first durable task platform. Instead of replaying code, it snapshots the whole process with Checkpoint/Restore in Userspace (CRIU) at each wait point and restores it later. This design drives most of the differences with the Workflow SDK.

Choose the Workflow SDK when you want durable orchestration that runs in your existing app, a portable open-source backend you can self-host, TypeScript and Python, and broad framework support. Choose trigger.dev when you want a managed task platform with no determinism constraints and use only TypeScript.

At a glance

Workflow SDKtrigger.dev
CategoryOpen-source durable-functions SDK that runs in your appDurable task platform with its own runtime (Cloud or self-hosted)
Durability modelEvent log + deterministic replay (workflow body must be deterministic)Process checkpoint/restore (CRIU): snapshots memory, CPU, and file descriptors; no determinism constraints, code runs as-is
Authoring"use workflow" / "use step" in your existing apptask() / schemaTask() deployed to trigger.dev as a separate target (Docker image)
LanguagesTypeScript / JavaScript (Python beta)TypeScript / JavaScript only
Where it runsCo-located with your app (Vercel managed or self-host)trigger.dev's run engine (isolated containers)
VersioningRuns pinned to immutable deployment, safe by defaultAtomic versioning: runs lock to their deploy version; new deploys never touch in-flight runs (same safety property)
AI and streamingWorkflowAgent in the AI SDK; native resumable streamingAI SDK tools, native useChat transport, resumable Realtime, durable multi-turn Sessions, human-in-the-loop (HITL) via wait.forToken
Concurrency controlEnforce in steps / at the publisherFirst-class queues + concurrency keys
PortabilityApache-2.0; World abstraction; runs anywhere Node runsApache-2.0; self-host on Docker/Kubernetes, but CRIU needs a compatible host (heavier than plain Docker); TypeScript-only
PricingSDK free; pay your platformCloud: compute-seconds + per-run ($0.0000338/s Small + $0.000025/run); no charge while checkpointed
Limits50 MB payload; 2 GB/run; no duration cap (Vercel World limits)3 MB payload / 10 MB output; 14-day maximum run lifetime; CPU-time-based maximum duration

What the limits mean in practice: trigger.dev caps task payloads at 3 MB and outputs at 10 MB (large model contexts and transcripts need external storage), and the 14-day maximum run time means human-in-the-loop flows that wait longer than two weeks can't complete in one run. The Vercel World limits are 50 MB payloads, 2 GB of state per run, and no run-duration cap.

The core difference: checkpoint/restore vs. replay

trigger.dev freezes the entire operating system process with CRIU when a task hits a wait point, then restores it later, so there's no replay and no determinism rule: you can call Date.now() or Math.random() anywhere, and prior steps don't re-execute. The cost is an execution model that requires CRIU-capable infrastructure (which makes self-hosting heavier than a plain container) and runs on trigger.dev's runtime as a separate deploy target.

The Workflow SDK reconstructs state by replaying the workflow function against its event log. That requires the workflow body to be deterministic (side effects go in "use step" functions), but it runs inside your existing app and deployment with no special host requirements, and the World abstraction lets you swap the storage/queue/stream layers.

Notably, both pin runs to a version so deploys never corrupt in-flight work: trigger.dev via atomic version-locking, the Workflow SDK via immutable-deployment pinning.

AI agents

trigger.dev offers AI SDK tool wrapping, a native useChat transport over its Realtime layer, resumable streaming, and durable multi-turn Sessions. The Workflow SDK offers WorkflowAgent directly inside the AI SDK plus native resumable streaming. Both support human-in-the-loop workflows (trigger.dev's wait.forToken and the Workflow SDK's hooks). Key differences are language support (trigger.dev is TypeScript-only; the Workflow SDK adds Python) and whether the agent runs in your app or on a dedicated platform.

Migrating from trigger.dev

trigger.devWorkflow SDKNote
task({ id, run })"use workflow" function started with start()No factory or id registry.
schemaTask({ schema, run })Typed function + "use workflow"Validate inputs at the call site.
Inline run body"use step" functionsSide effects move into named steps.
wait.for / wait.untilsleep('5m') / sleep(date)Import from workflow.
wait.forToken({ timeout })createHook() + Promise.race with sleep()Hooks carry a typed token.
triggerAndWait()start() called directly from the workflow, then await the returned RunSpawn + collect.
batch.triggerAndWait()Promise.all over collected Run handlesStandard concurrency.
metadata.stream() / RealtimegetWritable() / named streamsClients read from the stream.
Run tags / metadata.set()setAttributes() / attributes option on start()Filter runs by key=value. See Attributes.
AbortTaskRunErrorFatalErrorStops retries immediately.

The task() factory collapses into a plain function, and because the workflow body is replayed, move side effects into steps:

workflows/order.ts
export async function processOrder(orderId: string) {
  'use workflow';
  const order = await loadOrder(orderId);
  return { orderId: order.id, status: 'completed' };
}

async function loadOrder(orderId: string) {
  'use step';
  const res = await fetch(`https://example.com/api/orders/${orderId}`);
  return res.json() as Promise<{ id: string }>;
}

trigger.dev's run body has full Node.js access. The Workflow SDK's "use workflow" body runs in a sandboxed virtual machine (VM). Side effects (fetch, Date.now(), Math.random(), and database access) must live inside "use step" functions. Orchestration stays in the workflow body.

Install the migration skill to translate a trigger.dev app automatically:

npx skills add https://github.com/vercel/workflow --skill migrating-to-workflow-sdk

trigger.dev features without a direct Workflow SDK equivalent

Each row is a trigger.dev capability the Workflow SDK does not replicate one-to-one, paired with how to cover it on the Workflow SDK side:

trigger.dev featureHow to cover it with the Workflow SDK
Concurrency keys / queue concurrency limitsEnforce limits inside steps or debounce at the publisher
schedules.task() / cronTrigger from Vercel Cron or a system cron calling start()
machine presets / custom imagesFunction resources are per-deployment (configured via your hosting platform)

Compiled from public documentation. Verify current trigger.dev limits and pricing against trigger.dev/docs. Not based on head-to-head benchmarks.