Trigger.dev vs Inngest

Durable AI agents and workflows need somewhere to run. Inngest orchestrates functions in your existing app step by step. Trigger.dev runs your code on its own managed compute. Choose Inngest if you work in Python or Go, your system is built around events fanning out to many functions, you want your agent code to ship in the same app and deploy, or you want built-in scoring and experiments. Choose Trigger.dev if you want a TypeScript-first platform built for AI agents: durable chat agents with chat.agent, versioned prompts you can change without a redeploy, evals you write as ordinary tasks, custom dashboards over your runs and AI SDK calls, and agents that run as long as they need on managed compute, with no step or request timeout.

What is Trigger.dev?

Trigger.dev is the open source platform for building durable AI agents and workflows in TypeScript. Your code runs on managed compute as normal TypeScript, with no determinism constraints and no platform-imposed execution timeout. It includes built-in retries, queues, and scheduling, plus OpenTelemetry observability with custom dashboards and an SQL-style query language. Tasks can stream data to your frontend and backend in real-time, receive typed input while running, and pause for hours, days, or weeks for human approval or external events. Thousands of engineering teams run production workloads on it, processing hundreds of millions of runs.

What is Inngest?

Inngest is a durable execution platform that orchestrates functions in your own app via HTTP callbacks or persistent outbound connections (connect()). It's often used with serverless platforms like Vercel, but it also works on regular servers and containers. It supports TypeScript, Python, and Go with adapters for 20+ frameworks including Next.js, Express, Remix, and Hono. Inngest's step-based memoization ensures that completed work is never repeated on retry. The event-driven model with step.waitForEvent(), built-in concurrency controls, rate limiting, and debouncing make it well-suited for event-driven architectures. AgentKit adds AI agent orchestration with MCP tool support and React hooks for streaming agent output.

Feature deep-dive

How does the execution model differ?

Inngest orchestrates your code on your own infrastructure, subject to your host's limits. Trigger.dev runs your code on managed compute with no platform-imposed timeout.

FeatureTrigger.devInngest
Where your code runsManaged compute on Trigger.dev Cloud, or your own infrastructure if you self-hostYour own app
Uninterrupted execution limit (per task / per step)No platform limit. You set your own maxDuration (it counts compute time, not waits), or turn it off with timeout.NonePer step: your host's request timeout (Vercel: up to 800s, Lambda: 15 min), capped at 2 hours
Step modelNo steps required, write regular TypeScript. Subtasks with idempotency keys are the units that don't re-run on retrySteps are memoized. The TS SDK runs sequential steps in one request by default, and replays on retry or parallel steps
Replay behaviorNone (checkpoint-resume snapshots)Memoized replay (checkpointing enabled by default, executes sequential steps eagerly)
Non-deterministic codeWrite anything, anywherePlace inside step.run() to avoid re-execution on replay
System dependenciesBuild extensions (Prisma, FFmpeg, Playwright, Puppeteer, Python, apt packages, and more) or write your ownWhatever your host provides (on your own servers or containers you can install anything)
Total workflow durationNo platform limit. Waits don't count toward maxDurationMany steps and waits per run, up to the plan's max run length (30 days on Free, 90 on Pro, 366 on Business)
Running steps longer than your host's timeoutNot needed. Tasks have no platform timeoutInngest calls your app over HTTP to run steps, so each step runs within your host's request timeout. On an always-on server, you can use connect() instead, and each step can run for up to 2 hours

Inngest's callback model means your functions stay on your infrastructure, and Inngest handles orchestration, retries, and scheduling via HTTP. This works well when each step completes within your platform's timeout. For longer tasks, Inngest's connect() mode provides a WebSocket alternative for long-running servers. Durable Endpoints (in beta) add step-based checkpointing to regular HTTP handlers in Next.js and Bun. Trigger.dev runs your code on its own compute instead, so a task that takes 30 seconds or 30 minutes runs the same way, without depending on your host's request timeout (you set a maxDuration per task, or turn it off).

How does developer experience compare?

Inngest provides a rich step-function API with event triggers, sleep, and fan-out primitives. Trigger.dev has a simpler model: tasks that run as plain TypeScript with built-in queues and scheduling.

FeatureTrigger.devInngest
Core conceptTasksFunctions with steps
Trigger typesDirect trigger, batch trigger, scheduled (cron + dynamic schedules)Events, cron, webhooks
Child task invocationtriggerAndWait / batchTriggerAndWaitstep.invoke()
Waiting for external inputWaitpoints (wait hours, days, or weeks, with an optional timeout)step.waitForEvent() (requires a timeout)
Sleepingwait.for() / wait.until() (days, months, or longer)step.sleep() (up to the plan's max run length: 30 days on Free, 90 on Pro, about 1 year on Business)
Framework integrationsAny Node.js/TypeScript project20+ adapters (Next.js, Express, Remix, Hono, etc.)
Local developmentHot reload via CLI (requires internet)Local Dev Server (runs on your machine, no account or keys)
DebounceBuilt-in with leading/trailing modesBuilt-in debounce per key (1s to 7d period, optional max timeout)
Type safetyFull TypeScript types, schemaTask with Zod, ArkType, Valibot, TypeBox, etc.Full TypeScript types (Standard Schema: Zod, Valibot, ArkType)
AI coding toolsMCP server (docs, metrics, trigger, monitor, deploy), skills, llms.txtMCP servers (dev server and Cloud), agent skills, Claude Code and Codex plugins, llms.txt

Inngest's DX shines in event-driven architectures. Define a function, specify an event trigger, and Inngest calls your code when the event fires. The step primitives (step.run(), step.sleep(), step.waitForEvent()) are well-designed and intuitive for breaking work into durable units. Inngest supports Standard Schema validation for type-safe event payloads. Trigger.dev's model is different: define a task, trigger it from your code, and it runs on managed compute as plain TypeScript, close to a normal async function. Both platforms ship MCP servers and agent skills for AI editors. Inngest's plugins bundle skills, MCP config, and an eval harness for Claude Code and Codex. Trigger.dev's MCP server connects to the cloud platform for deploying, triggering tasks, and monitoring runs. Its skills (npx trigger.dev@latest skills) are version-pinned to your installed SDK, and a one-line setup prompt takes a coding agent from login to a first local run.

How does durability work in each platform?

Inngest memoizes each completed step and replays to resume. Trigger.dev continues from a snapshot after waits, and on failure retries, reusing subtasks with idempotency keys.

FeatureTrigger.devInngest
Durability modelCheckpoint-resume (process snapshots)Step-based memoization with function replay
On failure recoveryRetry from the start, reusing completed subtask results (with idempotency keys)Replay function, skip memoized steps
Continuing after a waitRestore the process snapshot on the same lineReplay function, skip memoized steps
Code constraintsNo determinism rules. Retries start from the top, and subtasks with idempotency keys return their saved resultsSide effects go inside step.run()
Max steps per runNo step concept, so no step limit1,000 steps per function
Step return data limitNo limit on in-process data. Task payloads up to 3 MB and outputs up to 10 MB, offloaded to object storage automatically4 MB per step return
Function state sizeGrows with process memory32 MB total

Inngest's memoization model: wrap each unit of work in step.run(), and if the function retries, completed steps return their cached result instead of re-executing. Inngest's TypeScript SDK enables checkpointing by default, executing sequential steps eagerly on your server without a round-trip per step, which lowers inter-step latency. Standard replay kicks in on failure or parallel steps. When a run resumes after a wait or a failure, it walks through previously completed steps, so a function with many steps carries more replay overhead at those points. Trigger.dev uses checkpoint-resume instead: the platform snapshots your entire process state at wait points and restores it later. Your code runs forward from the checkpoint rather than replaying from the start, so step count doesn't affect resume cost. When a run fails, Trigger.dev retries it from the start, and subtasks triggered with idempotency keys return their saved results instead of running again.

How do AI agent capabilities compare?

Inngest has AgentKit, a dedicated framework for multi-agent orchestration with MCP tools and React hooks. Trigger.dev runs any TypeScript AI framework with no platform-imposed timeout, real-time streaming, and human-in-the-loop primitives.

FeatureTrigger.devInngest
Durable chat agentschat.agent: one durable machine per conversation, no platform timeout, memory across turnsAgentKit (agents run inside the step + replay model)
AI framework approachAny TS framework (AI SDK, Mastra, OpenAI Agents SDK, etc.)Any model SDK inside steps (durable agents in TS, Python, or Go), plus the optional AgentKit framework (TS)
Tasks as AI toolsai.toolExecute() exposes tasks to the Vercel AI SDKAgentKit tool system with MCP support
Real-time updatesRun updates (status, metadata) + Streams (AI tokens, progress) to frontend and backendRealtime channels and topics built into the SDK, with a useRealtime React hook
Frontend hooksuseRealtimeRun, useRealtimeStream, useWaitToken, useInputStreamSend, etc.useRealtime, plus AgentKit's useAgent (docs also describe useChat and useThreads)
Human-in-the-loopWaitpoints pause a task for approval (hours, days, or weeks)step.waitForEvent() (max timeout)
Bidirectional communicationInput streams (typed data into running tasks)Send events to waiting steps
Maximum uninterrupted execution per task/stepNo platform limit (you set maxDuration, or turn it off)Per step: your host's timeout, capped at 2 hours
Multi-language agentsTypeScript (Python scripts via build extension)AgentKit: TypeScript only. General functions: TypeScript, Python, Go
Agent environmentFully customizable machine via build extensions (Python, Playwright + browsers, FFmpeg, system packages), with configurable CPU/RAM per runYour host's runtime and limits, plus Sandboxes (access-gated beta) for isolated microVM code execution

Inngest's main approach is durable agents: you write the agent loop with any model SDK, and each LLM or tool call is a step. Inngest's AgentKit adds a structured framework on top: define tools, configure models (OpenAI, Anthropic, Gemini, Grok, and OpenAI-compatible models), and use routing to coordinate multiple agents. AgentKit's React hooks stream agent output to the frontend. AgentKit agents run within Inngest's step-based execution model, so each LLM call is a memoized step with automatic retry. step.ai.infer() proxies LLM requests through Inngest's gateway, reducing serverless compute costs while waiting for responses. Trigger.dev works with any TypeScript AI framework directly: AI SDK, Mastra, OpenAI Agents SDK, or others, with no wrappers. ai.toolExecute() exposes tasks as tools for the Vercel AI SDK. Realtime pushes run updates and streams data (AI tokens, progress) to your frontend or backend, input streams send typed data into running tasks (cancel signals, approvals, user messages), and long-running agent conversations aren't bound by a platform timeout. For chat specifically, chat.agent gives every conversation its own durable machine that you point the AI SDK's useChat at, with run tracing and an AI metrics dashboard (tokens, cost, and latency per model) built in. Because tasks run on managed compute you shape with build extensions, an agent can drive a real browser (Playwright), run Python, or use FFmpeg without bundling any of it into a serverless function.

What infrastructure do you need to manage?

Inngest adds durability to your existing infrastructure. Trigger.dev provides the compute for background work on Trigger.dev Cloud, or you self-host it.

FeatureTrigger.devInngest
Compute providerTrigger.dev Cloud (managed) or self-hostedYour own hosting (serverless, servers, or containers)
Infrastructure to manageNone (cloud) or Docker Compose/K8s (self-hosted)Your app's deployment + an Inngest endpoint or worker
Build customizationBuild extensions (Prisma, FFmpeg, Playwright, Python, custom)Whatever your hosting platform supports
Deploy integrationsGitHub auto-deploy, Vercel integration (env var sync, version skew protection), CLISyncs on deploy via PUT to your serve endpoint
EnvironmentsProduction, Staging, Preview (per-branch), DevelopmentProduction, branch environments (auto-archive, Vercel/Netlify/Render)
Compute isolationEach run gets its own container (configurable CPU/RAM)Whatever your host provides

If you already have an app deployed, Inngest's model is convenient: add the SDK, expose an endpoint, and Inngest orchestrates your existing infrastructure. You keep your current hosting, CI/CD, and deployment pipeline. The tradeoff is that background jobs then run under your web app's limits (on serverless, that means the same timeouts, cold starts, and runtime as your web requests). Trigger.dev provides its own compute, so background tasks are decoupled from your web app entirely. Run FFmpeg, Playwright, or long-running AI agents without worrying about serverless limits. Build extensions add system dependencies with a config line. The Vercel integration syncs environment variables and adds version skew protection, and preview branches create isolated environments per PR with their own runs, schedules, and branch-level env vars.

How does pricing compare at scale?

Inngest bills per execution, counting the run plus each step (a 5-step run is 6 executions). Trigger.dev bills per compute-second plus a per-run fee. The models favor different workload shapes.

FeatureTrigger.devInngest
Pricing modelCompute-seconds + per-run feePer-step execution + concurrency tiers
Free tierFree plan with monthly usage included50,000 executions/mo, 5 concurrent steps
Pro tierSee pricing Pro tier with more executions and concurrency (see pricing )
What counts as a billable unitCompute time (per second, by machine size) plus a flat fee per task run, however many steps it hasExecutions: 1 when the run starts, plus 1 for each step
Self-hosted costFree (Apache 2.0) + your infraFree (SSPL) + your infra

Inngest's per-execution pricing scales with function complexity. Each run counts as the run itself plus every step, so a 5-step run is 6 executions and 100,000 runs of that function is 600,000 executions against your plan. This model works well for simple functions with few steps. Trigger.dev charges for compute time: a task that runs for 10 seconds costs the same whether it has 1 logical step or 50 internal operations. Which is cheaper depends on the workload. On Inngest, add your own hosting bill to the execution count. On Trigger.dev, cost depends on machine size and run time (including retries), plus a per-run fee for every task and subtask, so a workflow that splits work into subtasks, like the order example below, pays several run fees. Many-step work often favors Trigger.dev, while short functions with few steps can cost less on Inngest.

How does observability compare?

Inngest provides traces, Insights SQL queries with an AI assistant, and an AI cost dashboard. Trigger.dev adds user-built dashboards and Ask Trigger.

FeatureTrigger.devInngest
TracingOpenTelemetry spans per run with structured logsBuilt-in function traces with step-level detail
Live run updatesRuns page updates liveFunction run dashboard
Custom queriesTRQL (SQL-style, backed by ClickHouse)Insights : SQL over events, runs, steps, and spans (backed by ClickHouse), with saved, shared queries
Custom dashboardsCharts, tables, big number widgets with drag-and-drop layoutBuilt-in metrics and AI Overview dashboards, with Datadog and Prometheus export
AI query assistantDescribe what you want in plain English, generates TRQLInsights AI generates SQL from plain English
Dashboard agentAsk Trigger (beta): chat with an agent over your runs, errors, queues, and deploys for debugging, root-cause analysis, health reports, and TRQL analyticsNot available
AI-specific metricsAI metrics dashboard (tokens, cost, latency per model) plus custom OTel metricsAI Overview dashboard (tokens, cost, latency by model and function) from OpenTelemetry data
Prompt managementVersioned prompts with overrides, tracked per runNo built-in prompt store; experiments (group.experiment()) compare prompt or model variants on live traffic
AlertingRun failure, deployment, and error-group alerts (email, Slack, webhook)Function failure notifications
Trace retentionVaries by plan (see pricing )Varies by plan (see pricing )

Inngest provides built-in function traces with step-level detail, an AI Overview dashboard for LLM cost and latency, and Insights, a SQL editor over events, runs, and spans with an AI assistant that writes queries. Trigger.dev ships OpenTelemetry tracing with span-level detail, plus TRQL , an SQL-style query language backed by ClickHouse. Build custom dashboards with charts, tables, and big number widgets, or describe what you want in plain English and the AI assistant generates the query. TRQL queries are also available via SDK and REST API for programmatic access.

How do self-hosting and licensing compare?

Inngest is source-available under the SSPL (not OSI-approved), converting to Apache 2.0 three years after each release. Trigger.dev is Apache 2.0, with every release open source immediately.

FeatureTrigger.devInngest
LicenseApache 2.0SSPL (converts to Apache 2.0 after 3 years)
OSI-approved open sourceYesNo
Self-hosted setupDocker Compose or Kubernetesinngest start (SQLite default) or Helm chart (Kubernetes with Postgres + Redis)
Self-hosted scaleMulti-node (Kubernetes)Single-node (SQLite) or multi-node (Kubernetes with Postgres, KEDA autoscaling)
Feature parity with cloudCore platform on the same codebase. Checkpoints (non-blocking waits), warm starts, and auto-scaling are Cloud-only Enterprise SSO on Cloud only

Inngest's self-hosting story starts simple: inngest start runs everything in one process with SQLite. Point it at Postgres and Redis for production, or use the Helm chart for multi-node Kubernetes deployments with KEDA autoscaling. The SSPL license allows internal use but prevents competing managed services, and enterprise SSO is a Cloud feature. Trigger.dev self-hosts on Docker Compose or Kubernetes under Apache 2.0 with the same core codebase as Cloud (checkpoints, warm starts, and auto-scaling are Cloud-only ).

Code comparison

AI document summarizer

import { task } from "@trigger.dev/sdk";
import { generateText } from "ai";
import { anthropic } from "@ai-sdk/anthropic";
export const summarizeDoc = task({
id: "summarize-doc",
run: async (payload: { documentUrl: string }) => {
const doc = await fetch(payload.documentUrl).then(r => r.text());
const { text } = await generateText({
model: anthropic("claude-sonnet-4-6"),
prompt: `Summarize this document:\n\n${doc}`,
});
return { summary: text };
},
});

Multi-step order processing workflow

import { idempotencyKeys, task } from "@trigger.dev/sdk";
export const chargePayment = task({
id: "charge-payment",
retry: { maxAttempts: 5 },
run: async ({ orderId, amount, method }: { orderId: string; amount: number; method: string }) => {
// Stripe's own key stops a retry of this task charging twice
return await stripe.charges.create({ amount, source: method }, { idempotencyKey: `charge-${orderId}` });
},
});
export const sendOrderEmail = task({
id: "send-order-email",
retry: { maxAttempts: 3 },
run: async ({ to, order }: { to: string; order: Order }) => {
await sendEmail({ to, subject: "Order confirmed", body: formatConfirmation(order) });
},
});
export const processOrder = task({
id: "process-order",
run: async (payload: { orderId: string; userId: string }) => {
const order = await db.orders.find(payload.orderId);
const user = await db.users.find(payload.userId);
// If this run retries, it starts again from the top. Idempotency keys
// stop it triggering the charge or the email a second time.
const charge = await chargePayment.triggerAndWait(
{ orderId: order.id, amount: order.total, method: user.paymentMethod },
{ idempotencyKey: await idempotencyKeys.create("charge") }
);
if (!charge.ok) throw new Error("Payment failed");
const email = await sendOrderEmail.triggerAndWait(
{ to: user.email, order },
{ idempotencyKey: await idempotencyKeys.create("email") }
);
if (!email.ok) throw new Error("Confirmation email failed");
// Records the order ID, so a retry of this run can't decrement twice
await db.inventory.decrementForOrder(order.id, order.items);
return { status: "completed", orderId: order.id };
},
});

What developers say about Trigger.dev

With Trigger.dev, we've summarized over a million student interactions in just a couple of weeks. We're incredibly thankful for tools like Trigger.dev that are empowering us to bring AI-driven solutions to educators and students at scale.

Ben Duggan

Ben Duggan

MagicSchool AI logo

Teams routinely find 200% more opportunities and increase proposal output by 70% using GovSignals. We build on Trigger.dev to make that level of scale practical.

Conner Aldrich

Conner Aldrich

GovSignals logo

With chat.agent, every conversation gets a real machine, which made our durable agents much more straightforward to build. The default tracing and observability make viewing and debugging agentic sessions incredibly easy.

Graham Tremper

Graham Tremper

Arena logo

Frequently asked questions

Can I migrate from Inngest to Trigger.dev?

Yes. Inngest's step.sleep() becomes wait utilities, step.waitForEvent() maps to Waitpoints, step.invoke() maps to triggerAndWait, and simple step.run() blocks become inline code, because Trigger.dev resumes after waits without replay. Side effects like a payment or an email go in a subtask with a stable idempotency key , which returns its saved result if the run retries, and the payment call itself passes the provider's idempotency key.

Does Inngest run my code or just orchestrate it?

Inngest orchestrates your code. It calls your app over HTTP (or a WebSocket with connect()) to run your steps, on your own infrastructure and within that host's limits. Trigger.dev runs your code on its own managed compute with no platform-imposed timeout.

I already have serverless functions. Why not just use Inngest?

If your background work always finishes inside your platform's request timeout and needs only what your serverless runtime provides, reusing your existing functions is a reasonable fit. The tradeoff is that your background jobs inherit your web app's constraints: execution timeouts, cold starts, and memory limits, and system dependencies like FFmpeg or a headless browser are packaged with your app and run within your host's limits. Trigger.dev runs background work on separate managed compute, so a job can run for minutes or hours, keep state across an AI agent's turns, and use any system dependency, without touching your web app's hosting.

Is Inngest open source?

Inngest is source-available under the SSPL, with an Apache 2.0 grant that takes effect three years after each release. The SSPL isn't OSI -approved and restricts offering Inngest as a competing hosted service, which mainly matters if you plan to resell it. Trigger.dev is Apache 2.0 from day one.

How do Inngest's platform timeouts affect my workflows?

When served from a serverless platform, Inngest steps run inside requests to your function, so they run within its timeout: 300 seconds by default on Vercel (up to 800) and 15 minutes on AWS Lambda. Inngest's connect() mode removes the HTTP request timeout on long-running servers, up to Inngest's own 2-hour step ceiling . Trigger.dev imposes no platform timeout: you set your own maxDuration, or turn it off.

How does Inngest's step replay work?

When a run resumes (after a wait, a retry, or parallel steps), Inngest re-enters your function from the beginning and injects memoized results for completed steps, so code outside step.run() runs again. Inngest's TypeScript SDK checkpoints by default , running consecutive steps in one request for lower latency. Trigger.dev uses checkpoint-resume instead: after a wait your code continues where it paused without replay, and a failed run retries from the start.

Which is better for AI agents: Inngest or Trigger.dev?

Inngest lets you build durable agents with any model SDK inside steps (TypeScript, Python, or Go), plus AgentKit, an optional TypeScript framework with tools, MCP support, and React hooks (useAgent, with useChat and useThreads described in its docs). Agents run within the step-based execution model with automatic memoization per LLM call. Trigger.dev runs any TypeScript AI framework (AI SDK, Mastra, OpenAI Agents SDK, etc.) with no platform-imposed timeout, ai.toolExecute() to expose tasks as AI SDK tools, Realtime Streams for token streaming, input streams for sending data to running tasks, and Waitpoints for human-in-the-loop.

How does pricing compare between Inngest and Trigger.dev?

Inngest charges per execution: the run itself plus every step (a function with 5 step.run() calls uses 6 executions), with a free tier of 50,000 executions per month. Trigger.dev charges per compute-second plus a per-run fee, with a free plan that includes monthly usage. Inngest's cost tracks step count (your host bills compute separately), while Trigger.dev's tracks compute time.

Can I self-host Inngest?

Inngest offers self-hosting with inngest start (SQLite by default, or Postgres and Redis for production) and a Helm chart for multi-node Kubernetes deployments with KEDA autoscaling. Trigger.dev self-hosts via Docker Compose or Kubernetes under Apache 2.0 with the same core codebase as Cloud. Checkpoints (non-blocking waits), warm starts, and auto-scaling are Cloud-only .

Can I use Inngest with long-running servers instead of serverless?

Yes. Inngest's serve() works on any HTTP server, and connect() uses outbound WebSockets designed for long-running servers on Render, Fly.io, or Kubernetes, in TypeScript, Python, and Go. Trigger.dev runs your code on managed compute regardless of your hosting setup, so this distinction does not apply.

What is the best background jobs solution for Next.js?

Inngest integrates tightly with Next.js via its serve() adapter at /api/inngest, so background jobs ship with your app and run within your Vercel plan's function limits. Trigger.dev works with any framework including Next.js and runs tasks on separate managed compute with no platform-imposed execution timeout. A job that outgrows a request, needs FFmpeg or a browser, or runs for hours doesn't force a refactor.