Workflow SDK vs Temporal
How the Workflow SDK compares to Temporal: execution model, where workers run, versioning, AI agents, pricing, and a concept-mapping migration guide.
Temporal is a durable-execution platform with seven language SDKs and large-scale production use. Temporal and the Workflow SDK share the same core model of durable orchestration through event-sourced replay. The operational differences are where your code runs, how you version it, and how it streams to clients.
Choose the Workflow SDK when you want durable execution inside your existing TypeScript app with no additional infrastructure to operate, deployment-pinned versioning, and native streaming for AI apps. Choose Temporal when you need SDKs for languages such as Go and Java, want a self-hostable control plane you own, or are standardizing a large organization on one orchestration backend across many languages.
At a glance
| Workflow SDK | Temporal | |
|---|---|---|
| Category | Open-source durable-functions SDK; managed on Vercel or self-hosted | Durable-execution platform; Temporal Cloud or self-hosted cluster |
| Durability model | Event log + deterministic replay ("use workflow" orchestrators, "use step" functions) | Event-sourced replay (Workflows + Activities). Same model: "use workflow" ≈ Workflow, "use step" ≈ Activity |
| Languages | TypeScript / JavaScript (Python beta) | Go, Java, TypeScript, Python, .NET, PHP, Ruby (7 SDKs) |
| Where execution runs | Orchestration + execution + observability co-located on your platform; private networking and end-to-end (E2E) encryption included on Vercel | You run and scale your own Workers. Temporal Cloud hosts orchestration only; workers connect outbound over the public internet (PrivateLink optional) |
| Versioning | Runs pinned to their immutable deployment, safe by default; opt-in deploymentId: 'latest' to upgrade | Editing workflow code can break in-flight runs (non-determinism errors); evolve safely via patch APIs or Worker Versioning (keep old worker fleets draining) |
| AI SDK & agents | WorkflowAgent ships in the AI SDK; durable agent loop; native resumable streaming (getWritable/getReadable, WorkflowChatTransport) | First-party @temporalio/ai-sdk and "Workflow Streams", both Public Preview; streaming rides on Signals/Updates (batched, history-bound) |
| Security | Zero-config per-run AES-256-GCM E2E encryption by default; platform security is per World (the Vercel World inherits Vercel's security posture) | Workers run your code on your infrastructure (never enters Temporal's plane); client-side E2E via a Codec Server you operate. Cloud: SOC 2 II, HIPAA, GDPR |
| Performance | No-penalty resume; serverless scale-to-zero (true suspension); up to 100,000 concurrency on Vercel | Self-managed workers are long-running; Cloud namespace default 500 actions/sec (auto-scales) |
| Portability | Apache-2.0 SDK; World abstraction swaps storage/queue/streams independently | MIT server; pluggable persistence (Cassandra/Postgres/MySQL), but an opinionated monolithic backend you run or pay for |
| Pricing | SDK free; pay your platform (Vercel: events + data) or only your infrastructure if self-hosted | Self-host = free software; Temporal Cloud bills per Action (from $50 per million) + storage |
| Limits | No run/sleep cap; 10,000 steps, 50 MB payload, 2 GB/run (Vercel World limits) | No run cap (Continue-As-New for long histories); event history capped at 51,200 events / 50 MB; 2 MB payloads |
What the limits mean in practice: Temporal caps payloads at 2 MB and event history at 51,200 events. A model context, tool transcript, or embedding batch that exceeds 2 MB requires external blob storage and claim-check plumbing. Long agent loops must use Continue-As-New before the history fills. The Vercel World limits (50 MB payloads, 2 GB of state per run, and no run or sleep caps) provide more space for contexts in the run itself.
The biggest difference: what you operate
Temporal Cloud manages the durable engine, but you still build, deploy, and scale a fleet of Workers that poll task queues and run your Workflow and Activity code. Those workers connect out to Temporal Cloud, typically over the public internet (AWS PrivateLink and Google Cloud Private Service Connect are available as same-region options). To make encrypted payloads readable in the Web UI, you must run a Codec Server.
With the Workflow SDK on Vercel, orchestration, execution, and observability are co-located on one platform with internal networking, and per-run E2E encryption is on by default with no codec server to run. There are no workers, task queues, or a control plane to operate. (Self-hosting via the Postgres World is the closest analog to running your own Temporal cluster.)
Versioning
This is where the two differ most in day-to-day risk. Because both replay code against history, changing workflow code mid-flight is the hazard.
- Temporal: Editing a workflow can produce a non-determinism error that breaks or stalls open executions. You can evolve workflows with patch APIs (
patched()/GetVersion(), which accumulate patch branches) or Worker Versioning (Build IDs / Worker Deployments pin workflows to a build and keep the old worker fleet running until it drains). You must manage this process for every long-running workflow. - Workflow SDK: Runs are pinned to the immutable deployment that started them. Shipping new code never touches in-flight runs because they keep replaying against the exact code they began on. Upgrading a run is explicit and opt-in (start it with
deploymentId: 'latest', or self-restart at a checkpoint). This model requires no patch branches or draining worker fleets.
AI agents and streaming
Both target AI agents, but the integration depth differs. The Workflow SDK's WorkflowAgent is a first-class construct inside the AI SDK (@ai-sdk/workflow): the agent loop becomes a durable workflow, each tool execute marked "use step" is an auto-retried durable step, and partial output streams through durable, resumable streams that survive reconnects and cold starts.
Temporal ships a first-party @temporalio/ai-sdk plugin and a "Workflow Streams" library, but both are Public Preview, and streaming is built on Signals/Updates: every chunk is written to history, so it's batched rather than per-token.
Migrating from Temporal
The model maps closely. Keep your orchestration logic; drop the workers, task queues, and activity modules.
| Temporal | Workflow SDK | Note |
|---|---|---|
| Workflow Definition / Execution | "use workflow" function started with start() | Orchestration stays in the workflow function. |
| Activity | "use step" function | Side effects and Node.js access live in steps. |
| Worker + Task Queue | Managed execution | No worker fleet or polling loop to operate. |
| Signal | createHook() / createWebhook() | Hooks for typed resume signals; webhooks for HTTP callbacks. |
| Query | getWritable({ namespace: 'status' }) stream | Stream status durably; clients read the stream instead of polling. |
| Child Workflow | "use step" wrapper around start() / getRun() | Return the Run object so observability can deep-link. |
| Activity retry policy | maxRetries, RetryableError, FatalError | Retries live at the step boundary. |
| Event History | Workflow event log / run timeline | Same durable replay; built-in observability UI. |
A minimal translation, where the orchestrator loses proxyActivities and becomes plain TypeScript:
export async function processOrder(orderId: string) {
'use workflow';
await chargePayment(orderId);
return { orderId, status: 'completed' };
}
async function chargePayment(orderId: string) {
'use step';
await fetch(`https://example.com/api/orders/${orderId}/charge`, { method: 'POST' });
}Signals become hooks, where one createHook() + await replaces a signal definition, handler, and condition() guard:
import { createHook } from 'workflow';
export async function refundWorkflow(refundId: string) {
'use workflow';
using approval = createHook<{ approved: boolean }>({
token: `refund:${refundId}:approval`,
});
const { approved } = await approval; // suspends durably until resumed
return { refundId, approved };
}Install the migration skill to translate a Temporal app automatically:
npx skills add https://github.com/vercel/workflow --skill migrating-to-workflow-sdkTemporal features without a direct Workflow SDK equivalent
Each row is a Temporal capability the Workflow SDK does not replicate one-to-one, paired with how to cover it on the Workflow SDK side:
| Temporal feature | How to cover it with the Workflow SDK |
|---|---|
| Search attributes / visibility queries | Filter runs by status and timestamps via getRun() and the observability UI |
Per-activity timeouts (startToCloseTimeout, etc.) | Enforce deadlines inside a step with AbortSignal.timeout(ms), or wrap a call in Promise.race(step(), sleep('5m')) |
Rich retry policy (backoffCoefficient, nonRetryableErrorTypes) | Only maxRetries is configurable; classify with RetryableError / FatalError and set delay via new RetryableError(msg, { retryAfter: '5s' }) |
| Polyglot workers | The Workflow SDK is TypeScript-first (Python in beta); for Go/Java/etc. in the same orchestrator, Temporal remains the better fit |
Compiled from public documentation. Verify current Temporal pricing, limits, and preview-feature status against temporal.io/docs. Not based on head-to-head benchmarks.