workflow
Version:
Workflow SDK - Build durable, resilient, and observable workflows
103 lines (78 loc) • 8.95 kB
text/mdx
---
title: Workflow SDK vs Inngest
description: How the Workflow SDK compares to Inngest, event-driven durable functions that run on your own infrastructure over HTTP, with a concept-mapping migration guide.
type: conceptual
summary: Inngest is an event-driven durable-functions platform that invokes your code over HTTP and memoizes step results. The Workflow SDK co-locates orchestration and execution and replays from an event log.
prerequisites:
- /docs/foundations/workflows-and-steps
related:
- /docs/foundations/hooks
- /docs/foundations/streaming
- /docs/ai
---
[Inngest](https://www.inngest.com) is a durable-functions platform with an **event-driven** core: functions trigger on events or cron, and Inngest invokes your code (running on your own infrastructure) one step at a time over HTTP, memoizing each step's result. It overlaps heavily with the Workflow SDK, with a different execution topology and a strong AI/agent story on both sides.
<Callout type="info">
**Choose the Workflow SDK** when you want orchestration and execution co-located (no per-step HTTP round trips), deployment-pinned versioning, and a supported open-source self-hosting path. **Choose Inngest** when an event-bus model fits your architecture and you want built-in flow controls for concurrency, throttling, debounce, batching, and priority.
</Callout>
## At a glance
| | Workflow SDK | Inngest |
| --- | --- | --- |
| **Category** | Open-source durable-functions SDK | Durable functions on an event-driven platform |
| **Durability model** | Event log + deterministic replay | **Step-result memoization** (each `step.run` runs once; completed steps are skipped), not whole-function replay |
| **Trigger model** | Direct `start(workflow, [args])` (import the function) | Event bus (`inngest.send`) + cron; loosely coupled publishers/consumers |
| **Where execution runs** | Orchestration + execution co-located on your platform | **Your code runs on your infrastructure**; Inngest invokes it per step over HTTP (Serve) or a persistent worker connection (Connect, in public beta) |
| **Languages** | TypeScript / JavaScript (Python beta) | TypeScript; Python and Go (production, pre-1.0) |
| **Versioning** | Runs pinned to immutable deployment | Tracked by step-ID hashes: hot-edit functions, but editing a step's logic under the **same ID** reuses the old memoized result for in-flight runs; rename the ID or route a new function by timestamp for rewrites |
| **AI & streaming** | `WorkflowAgent` in the AI SDK; native resumable streaming | Native AI SDK via `step.ai.wrap`; **AgentKit** multi-agent framework and durable **Realtime** (`step.realtime.publish`) + `useAgent` hook, both Developer Preview |
| **Security** | Zero-config per-run end-to-end (E2E) encryption by default; platform security is per World (the Vercel World inherits Vercel's security posture) | Runs on your infrastructure; signed requests; first-party E2E encryption middleware (TypeScript and Python); SOC 2 Type II, HIPAA add-on |
| **Portability** | Apache-2.0; World abstraction; **self-host supported** | Engine open source (Server Side Public License); self-host via single Go binary + Postgres, but **self-hosting is community/best-effort**: no support service-level agreement, and the `inngest start` binary is Beta (the hosted service is the default) |
| **Pricing** | SDK free; pay your platform | Per-execution: billed for the run **plus each step plus retries**; Pro from $99/mo, then ~$50 per 1M executions |
| **Limits** | 50 MB payload; 2 GB/run; 10,000 steps ([Vercel World limits](https://vercel.com/docs/workflows/pricing)) | 1,000 steps/function; 4 MiB step payload; 32 MiB run state; runs up to 366 days |
**What the limits mean in practice**: Inngest's caps are restrictive for real long-running AI workloads. An agent loop spends steps on every model and tool call, so it can consume 1,000 steps per function; a single large language model response can approach the 4 MiB step-payload cap; and an accumulated conversation or context can outgrow 32 MiB of run state. The [Vercel World limits](https://vercel.com/docs/workflows/pricing) are 50 MB per payload and 2 GB of state per run.
## Topology: co-located vs. invoked-over-HTTP
Inngest's engine lives outside your code and calls your functions step-by-step over HTTP (or a Connect worker). That keeps your code on your own infrastructure for portability and data locality, but adds a network round trip per step. This overhead matters for workflows with many small sequential steps. The Workflow SDK co-locates orchestration and execution on one platform, so steps don't require a per-step HTTP request.
Triggering also differs. Inngest is event-driven (publishers `send` events; functions subscribe), which supports loosely coupled fan-out. The Workflow SDK's `start()` imports the workflow function directly, providing tighter coupling and stronger type safety. For event-bus-style fan-out, wrap `start()` in a shared publisher.
## Versioning
Inngest doesn't use version numbers; it keys state by **step-ID hash**, so you can edit functions while runs are in flight. The catch: if you change the logic *inside* a step but keep the same ID, in-flight runs that already completed that step silently reuse the **old** memoized result: only new runs see the change. To force re-execution you rename the step ID, and for incompatible rewrites the recommended pattern is a new function with timestamp-based event routing.
The Workflow SDK pins each run to its immutable deployment, so in-flight runs always finish on the exact code they started with, and upgrades are explicit: no per-step-ID reasoning required.
## AI agents
Inngest offers `step.ai.wrap()` (wrap Vercel AI SDK calls as durable steps), **AgentKit** (a multi-agent framework with Model Context Protocol (MCP) tools), and durable **Realtime** streaming with a `useAgent` React hook, though AgentKit and Realtime are both Developer Preview. The Workflow SDK offers `WorkflowAgent` directly inside the AI SDK and native [resumable streaming](/docs/ai/resumable-streams). AgentKit fits event-driven applications that need an integrated agent framework. The Workflow SDK fits applications that need the agent loop to be a durable workflow with streaming built into the runtime.
## Migrating from Inngest
| Inngest | Workflow SDK | Note |
| --- | --- | --- |
| `inngest.createFunction()` | `"use workflow"` function started with `start()` | No factory or event binding. |
| `step.run()` | `"use step"` function | Named async function with Node.js access. |
| `step.sleep()` / `step.sleepUntil()` | `sleep('5m')` / `sleep(date)` | Import from `workflow`. |
| `step.waitForEvent()` | `createHook()` / `createWebhook()` | Token encodes the routing; no event schema. |
| `step.invoke()` | [`start()`](/docs/foundations/starting-workflows) called directly from the workflow | Spawn a child run. |
| `inngest.send()` / event triggers | `start()` from your app boundary | Start workflows directly. |
| Retry config (`retries`) / `RetryAfterError` | `maxRetries`, `RetryableError`, `FatalError` | Retries live at the step boundary. For custom backoff via `retryAfter`, see [Errors & Retrying](/docs/foundations/errors-and-retries#customize-retry-behavior). |
| `step.realtime.publish()` / Realtime | `getWritable()` / named streams | Clients read from the stream. |
The `createFunction` factory collapses into a plain exported function:
```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="info">
Install the migration skill to translate an Inngest app automatically:
```bash
npx skills add https://github.com/vercel/workflow --skill migrating-to-workflow-sdk
```
</Callout>
### Inngest features without a direct Workflow SDK equivalent
Each row is an Inngest capability the Workflow SDK does not replicate one-to-one, paired with how to cover it on the Workflow SDK side:
| Inngest feature | How to cover it with the Workflow SDK |
| --- | --- |
| Flow control (concurrency, throttling, debounce, rate limiting, batching, priority) | No direct function-level analog; enforce limits inside steps or debounce at the publisher before `start()` |
| Cron / scheduled functions | Trigger from Vercel Cron or a system cron calling `start()` |
| Event-bus fan-out by name match | Replace with explicit `start()` calls per target workflow |
---
*Compiled from public documentation. Inngest tier names and pricing vary across sources; verify against [inngest.com/pricing](https://www.inngest.com/pricing). Not based on head-to-head benchmarks.*