---
title: Workflow SDK vs trigger.dev
description: How the Workflow SDK compares to trigger.dev, including deterministic event-log replay versus CRIU process checkpoint/restore and a concept-mapping migration guide.
type: conceptual
summary: trigger.dev achieves durability by snapshotting the process with Checkpoint/Restore in Userspace (CRIU), so code has no determinism constraints. The Workflow SDK uses event-log replay and runs in your existing app.
prerequisites:
  - /docs/foundations/workflows-and-steps
related:
  - /docs/foundations/errors-and-retries
  - /docs/foundations/streaming
  - /docs/ai
---

# Workflow SDK vs trigger.dev



[trigger.dev](https://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.

<Callout type="info">
  **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.
</Callout>

## At a glance

|                         | Workflow SDK                                                                                                | trigger.dev                                                                                                                             |
| ----------------------- | ----------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| **Category**            | Open-source durable-functions SDK that runs in your app                                                     | Durable task platform with its own runtime (Cloud or self-hosted)                                                                       |
| **Durability model**    | Event 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 app                                                        | `task()` / `schemaTask()` deployed to trigger.dev as a separate target (Docker image)                                                   |
| **Languages**           | TypeScript / JavaScript (Python beta)                                                                       | **TypeScript / JavaScript only**                                                                                                        |
| **Where it runs**       | Co-located with your app (Vercel managed or self-host)                                                      | trigger.dev's run engine (isolated containers)                                                                                          |
| **Versioning**          | Runs pinned to immutable deployment, safe by default                                                        | **Atomic versioning**: runs lock to their deploy version; new deploys never touch in-flight runs (same safety property)                 |
| **AI and streaming**    | `WorkflowAgent` in the AI SDK; native resumable streaming                                                   | AI SDK tools, native `useChat` transport, resumable Realtime, durable multi-turn Sessions, human-in-the-loop (HITL) via `wait.forToken` |
| **Concurrency control** | Enforce in steps / at the publisher                                                                         | First-class queues + concurrency keys                                                                                                   |
| **Portability**         | Apache-2.0; World abstraction; runs anywhere Node runs                                                      | Apache-2.0; self-host on Docker/Kubernetes, but CRIU needs a compatible host (heavier than plain Docker); TypeScript-only               |
| **Pricing**             | SDK free; pay your platform                                                                                 | Cloud: compute-seconds + per-run ($0.0000338/s Small + $0.000025/run); no charge while checkpointed                                     |
| **Limits**              | 50 MB payload; 2 GB/run; no duration cap ([Vercel World limits](https://vercel.com/docs/workflows/pricing)) | 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](https://vercel.com/docs/workflows/pricing) 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](/worlds/building-a-world) 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](/docs/ai/resumable-streams). 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.dev                    | Workflow SDK                                        | Note                                |
| ------------------------------ | --------------------------------------------------- | ----------------------------------- |
| `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"` functions                              | Side effects move into named steps. |
| `wait.for` / `wait.until`      | `sleep('5m')` / `sleep(date)`                       | Import from `workflow`.             |
| `wait.forToken({ timeout })`   | `createHook()` + `Promise.race` with `sleep()`      | Hooks carry a typed token.          |
| `triggerAndWait()`             | `"use step"` wrappers around `start()` / `getRun()` | Spawn + collect.                    |
| `batch.triggerAndWait()`       | `Promise.all` over collected `Run` handles          | Standard concurrency.               |
| `metadata.stream()` / Realtime | `getWritable()` / named streams                     | Clients read from the stream.       |
| `AbortTaskRunError`            | `FatalError`                                        | Stops retries immediately.          |

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

```typescript title="workflows/order.ts"
export async function processOrder(orderId: string) {
  'use workflow'; // [!code highlight]
  const order = await loadOrder(orderId);
  return { orderId: order.id, status: 'completed' };
}

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

<Callout type="warn">
  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.
</Callout>

<Callout type="info">
  Install the migration skill to translate a trigger.dev app automatically:

  ```bash
  npx skills add https://github.com/vercel/workflow --skill migrating-to-workflow-sdk
  ```
</Callout>

### 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 feature                         | How to cover it with the Workflow SDK                                        |
| ------------------------------------------- | ---------------------------------------------------------------------------- |
| Concurrency keys / queue concurrency limits | Enforce limits inside steps or debounce at the publisher                     |
| `schedules.task()` / cron                   | Trigger from Vercel Cron or a system cron calling `start()`                  |
| `machine` presets / custom images           | Function resources are per-deployment (configured via your hosting platform) |

***

*Compiled from public documentation. Verify current trigger.dev limits and pricing against [trigger.dev/docs](https://trigger.dev/docs). Not based on head-to-head benchmarks.*


---

For a semantic overview of all documentation, see [/sitemap.md](/sitemap.md)

For an index of all available documentation, see [/llms.txt](/llms.txt)

For agent-facing discovery, including API and MCP surfaces, see [/agents.md](/agents.md)