Migrating production infrastructure? Get up to $10K in migration credits.

Apply now
Platform
Comparison
workflows

Render Workflows vs Inngest: durable compute vs durable orchestration

Inngest and Render Workflows both orchestrate multi-step jobs with automatic retries, but they start from different premises.

Inngest makes the orchestration durable around code that you host. It saves the result of every step and replays your function to recover. Your functions run on your own servers or serverless functions, and Inngest calls them for each step.

Render Workflows makes the compute durable, with a separate layer that runs your tasks, so you have no servers or workers to provision, scale, or patch. Each task run gets its own instance, and you set its compute plan (CPU and memory) for each task, up to 8 CPU and 32 GB. A run can last up to 24 hours. When Render retries a failed run, steps that already finished return their saved results.

This difference affects:

  • How you write workflows
  • Where each step runs
  • How much CPU, memory, and time each step can use
  • How each product bills for usage

The short answer

  • Choose Inngest if your workflows are event-driven, run for days or weeks, or need per-customer concurrency, throttling, or debouncing, and you already have a place to host the code.
  • Choose Render Workflows if your steps need more CPU, memory, or time than a single HTTP request to your app can get, such as video processing, large file parsing, or model inference. Each task runs on its own instance, sized up to 8 CPU and 32 GB RAM, for up to 24 hours.
  • Use both by running the event handling and long waits on Inngest and the heavy tasks on Render.

Render Workflows vs Inngest at a glance

Dimension
Inngest
Render Workflows
Durability model
Inngest saves each step's result and replays your function, returning saved results for completed steps
Each task run gets its own instance, and completed ctx.step() steps return saved results on retry and recovery
Where code runs
Your own servers or serverless functions, which Inngest calls over HTTP or reaches through Connect workers
Render provisions an instance for each task run
Languages
TypeScript, Python, and Go (a Kotlin/Java SDK exists but isn't listed as official)
TypeScript and Python
Max step duration
2 hours, or less if your host has a shorter timeout
2 hours by default, configurable up to 24 hours per task
Max compute per step
Whatever your host provides
8 CPU and 32 GB of RAM, with larger plans on request
Code constraints
Code outside steps runs again on every replay, and step IDs must stay stable
Code between steps runs again on every replay and must be deterministic, and side effects must be safe to repeat
Waiting and pausing
step.sleep() and step.waitForEvent() pause a run without compute
No pause primitive, so a run keeps its instance while it waits
Triggers and flow control
Event and cron triggers, with concurrency keys, throttling, rate limits, debounce, priority, and batching
Start runs from the SDK, REST API, CLI, or Dashboard, and schedule them with a Render cron job
Payload size
4 MiB per step result and 32 MiB of state per run
4 MB of arguments per task run
Data and networking
Depends on where you host your functions
Private network to Render Postgres, Key Value, and private services
Deploys and previews
Deploys with your app, which syncs its functions to Inngest, with branch environments for previews
Separate workflow service, declared with type: workflow in Blueprints, and not yet included in preview environments
Pricing model
Executions (each run and each step) and seats, plus your host's compute
Compute per run by the second, plus task state retention
Compliance
SOC 2 Type II, and a HIPAA BAA as an add-on on Pro and Business
SOC 2 Type 2 and ISO 27001, but Workflows is not available in HIPAA-enabled workspaces yet

What is Inngest?

Inngest is a durable execution platform for event-driven functions. You define functions with the Inngest SDK, give each one an event or cron trigger, and split its work into steps with step.run(). Your app exposes the functions through a serve endpoint that Inngest calls over HTTP. On long-running servers, you can use Connect instead, which opens an outbound connection from your workers to Inngest, so you don't expose an endpoint. Inngest queues each step, calls your code to run it, and stores the result.

Steps retry automatically, four times by default. step.sleep() pauses a run for up to a year, within your plan's maximum run length (30 days on the Free plan), and step.waitForEvent() pauses it until a matching event arrives or a timeout expires, without consuming compute in either case. Function options control concurrency, throttling, rate limits, debounce, priority, and event batching, and you can key most of them to a value such as a customer ID. The Inngest Dashboard shows traces for every run, and the Inngest Dev Server gives you a similar UI on your machine. You can self-host the Inngest server, a single binary that uses SQLite and an embedded Redis-compatible store by default, or external Postgres and Redis for larger installs.

What is Render Workflows?

Render Workflows is an end-to-end orchestration and execution engine for long-running, distributed tasks. You use the Render SDK for Python or TypeScript to mark functions as tasks, then deploy them as a workflow service from a Git repository. When you trigger a task, Render starts the run in its own isolated instance, retries it on failure, and removes the instance when the run completes.

Each task sets its own retry, timeout, and compute plan, and each execution of a task is a run. Inside a task, ctx.step() runs a plain function or a registered task in the same process, as a sequential step with its own retries. A task can also call other tasks with ctx.run(). Each chained run gets its own instance and returns its result to the parent, and you fan out with asyncio.gather or Promise.all. You can start runs from the SDK, the REST API, the Render CLI, or the Render Dashboard, which shows active and completed runs for each task with logs. Use render workflows dev to run and test a local task server before you deploy.

Where does durability live: in orchestration or in compute?

Inngest makes the orchestration durable, and Render Workflows makes the compute durable. As a result, the size of an Inngest step depends on where you host your code, and you set the size of each Render task in code.

In Inngest, every step runs inside your app. Per the usage limits, a step can run for up to 2 hours, but a shorter timeout on your host takes precedence. If you serve functions from a serverless platform, each step gets that platform's request duration, CPU, and memory. If you run Connect workers on long-running servers, each step gets the CPU and memory of the worker that picks it up. A run can chain up to 1,000 steps and sleep between them, and it can last up to 30 days on the Free plan, 90 days on Pro, and 366 days on Business, including sleeps. Inngest suits work made of many short calls: call an API, save the result, wait, call the next API.

With Render Workflows, every task run is its own instance. You pick the compute plan per task, from the default flex plan (up to 1 CPU and 4 GB of RAM) to 8c-32g (8 CPU and 32 GB of RAM). You set the timeout per task anywhere from 30 seconds to 24 hours.

Consider a pipeline that ingests uploaded videos. For each video, it downloads a 3 GB file, transcodes it to three resolutions, extracts audio, transcribes it with a speech model, and writes the results to Postgres. The transcode step can take 40 minutes, and a 4K source can push memory past 4 GB.

On Inngest, the transcode fits within the 2-hour step limit only if your host allows it. Many serverless platforms cap function duration well below 40 minutes, so you would run Connect workers on long-running servers with enough memory. Any worker in the app can pick up any step, so you size the whole worker fleet for the transcode, or move it into a separate app on larger machines. You also scale those workers yourself and pay for them while they're idle. Inngest Sandboxes, an access-gated beta on Pro and above, run code in separate microVMs, but the beta caps each sandbox at 4 vCPU, 4 GB of RAM, and one hour of active runtime.

On Render Workflows, the transcode is one task on a larger plan:

The parent task runs on the small default plan, and each transcode gets four CPUs and 16 GB of RAM. If one transcode fails, Render retries that run without rerunning the other two.

Choose Inngest if your steps are short API calls and the long part of the run is waiting. Choose Render Workflows if a single step needs more than your Inngest host allows, and you don't want to size and scale a worker fleet for your largest step.

Comparison by dimension

Programming model

Inngest recovers by replaying your function. Each completed step.run() returns its saved result instead of running again, but code outside a step can run again each time Inngest replays the function. You put database writes, API calls, and other side effects inside steps. Each step needs a stable ID in order to match saved results to steps. Function code can use any package in its language runtime.

With Render Workflows, a task is an ordinary function with full access to its language runtime and packages. Inside a task, ctx.step() runs a plain function or a registered task as a step, in the same process and in order. Each step retries on its own and saves its result. If the task runs again after a failed attempt or an infrastructure failure, each completed step returns its saved result. Render checks that each replay matches the original run and fails a replay that doesn't, so keep the code between your steps deterministic. Put side effects inside steps, and make them safe to repeat, for example by using upserts in database writes.

To move work onto its own compute, chain a run with ctx.run(). Each chained run executes on its own instance, retries on its own, and returns its result to the parent. Chain several runs at once to fan work out in parallel.

Both Inngest and Render save the result of each step inside a function. Render also lets you split a job into chained runs, each with its own instance, compute plan, and timeout.

Choose Inngest if you want durable steps inside the app you already deploy. Choose Render Workflows if you want durable steps plus the option to fan work out to separately sized instances that you deploy and scale apart from your app.

Languages

Render Workflows has SDKs for Python and TypeScript. Inngest has official SDKs for TypeScript, Python, and Go. TypeScript gets new features first, the Python SDK requires Python 3.10 or later, and some features are TypeScript-only, such as step.ai.wrap().

Choose Inngest if your services are in Go, or you want the widest feature set in TypeScript. Choose Render Workflows if your pipelines are in Python or TypeScript and you want the same features in both languages.

Waiting and human-in-the-loop

Inngest is built for long waits. step.sleep('wait-7-days', '7d') pauses a run without consuming compute, and step.waitForEvent() resumes it when a person approves a request or an external system sends an event. The cancelOn option cancels a run when a matching event arrives, including a run that is sleeping or waiting, though any step that has already started finishes before the run stops.

Render Workflows has no pause or sleep primitive yet, so a waiting run holds its instance until it completes or hits its timeout (24 hours at most). On the flex plan, Render bills only for the CPU and memory a run uses, so idle waiting costs little. For approval flows on Render, end the run and start a new one when the approval arrives.

Choose Inngest if runs wait days or weeks for people or events. Choose Render Workflows if each wait fits within the 24-hour task timeout, or you can split a longer wait into two runs.

Triggers and flow control

Inngest starts functions from events and cron schedules. One event can trigger several functions, and a cron trigger takes an optional time zone. Inngest also controls how fast runs start. You can cap concurrent steps per customer, throttle or rate-limit new runs, debounce bursts of events, set priority, and batch up to 100 events into one run on Pro.

Render Workflows starts runs when you call the SDK, the REST API, the Render CLI, or the Render Dashboard. To run a task on a schedule, create a cron job that triggers it. Render queues runs when a workflow service reaches its compute limits, but it has no configurable per-key concurrency, throttling, or debounce.

Choose Inngest if you need per-tenant limits or event fan-out. Choose Render Workflows if your app decides when to start each run.

Data and networking

Render Workflows task runs can connect to Render Postgres, Render Key Value, and private services in the same region over the private network, with no public internet hop. If the workflow belongs to a network-isolated environment, its runs can't reach other services in that environment over the private network. Inngest stores run state, including step results, in Inngest Cloud, or on your own Inngest server if you self-host. Your functions reach your data from wherever you host them. With serve, Inngest Cloud calls your endpoint over the public internet. With Connect, your workers open an outbound connection to Inngest, so they need no public endpoint.

Choose Inngest if your functions already run next to your data. Choose Render Workflows if you also need managed Postgres and web service hosting for your application.

Developer workflow

Inngest functions deploy with your app. When a deploy changes your function definitions, you resync the app so Inngest sees them. The Vercel and Netlify integrations do this automatically, and Connect apps sync when a worker connects. Branch environments give each Git branch its own isolated Inngest environment for preview deploys, and local development uses the Inngest Dev Server. Render Workflows deploys as a separate workflow service from a Git repository, and you declare it in a Blueprint with type: workflow. Compute plans live in task code, so the Blueprint has no plan field. Workflow services aren't included in preview environments. Run render workflows dev to test tasks locally.

Choose Inngest if you want workflows to ship in the same deployment as your app with preview branches. Choose Render Workflows if you want workflows deployed and scaled separately from your web app.

Pricing model

Inngest bills executions, per its pricing page. Each function run counts as one execution, and each step counts as another, so a function with five steps uses six executions per run. The Free plan includes 50,000 executions per month and 5 concurrent steps. Pro starts at $99 per month with 1 million executions and 100 concurrent steps, and extra executions cost from $0.000050 down to $0.000015 each, depending on volume. Business starts at $499 per month with 10 million executions. Each plan includes a set number of seats, with extra seats at $10 each on Pro and Business. Free includes 3 Connect workers, Pro includes 20, and Business includes 100, with more available as an add-on. You also pay your host for the compute that runs your functions.

Render Workflows bills compute for each run by the second, per its limits and pricing page. The flex plan bills $0.20 per CPU-hour of CPU time used and $0.05 per GB-hour of RAM, up to $0.40 per hour. Fixed plans bill a flat hourly rate, from $0.40 per hour for 2c-4g to $2.50 per hour for 8c-32g. Task state retention costs $0.25 per GB. Outbound traffic counts toward your workspace's bandwidth usage.

Choose Inngest if you run many small steps with long waits between them, on compute you already pay for. Choose Render Workflows if you want one compute meter that tracks how long and how large each task is.

Security and compliance

Both Inngest and Render hold SOC 2 Type 2 reports, and Render holds ISO 27001 certification. Inngest encrypts data at rest and in transit. With its encryption middleware, your servers encrypt step results, function output, and a designated event field before they reach Inngest, so Inngest can't read them. Inngest offers a HIPAA business associate agreement (BAA) as a paid add-on on Pro and Business, and lists it as included on Enterprise. Render offers a BAA on Scale and Enterprise plans, but Render Workflows isn't available in HIPAA-enabled workspaces.

Choose Inngest if your workflows process protected health information and Inngest confirms that your BAA covers them. Choose Render Workflows if your processes don't handle protected health information and your requirements are covered by SOC 2 Type 2 and ISO 27001.

AI and agent workloads

Many agents wait for approvals or model responses and run heavy compute between them, and Inngest handles the waits. step.ai.infer() sends a model request through Inngest, so a serverless function doesn't pay for compute while the provider responds, and AgentKit builds agents on top of Inngest functions. Render Workflows handles the compute. A task can run model inference on 8 CPUs, parse a large document set, or crawl for hours, and it can read and write to Postgres over the private network.

Choose Inngest if your agents run for weeks or months. Choose Render Workflows if your agents need managed compute with different CPU and memory for each task.

When to choose Inngest

  • Your workflows start from events, and one event can fan out to several functions.
  • Runs wait hours, days, or weeks for sleeps, approvals, or events, and you don't want to pay for compute while they wait.
  • You need concurrency limits, throttling, debounce, or batching per customer.
  • Every step fits in the time and memory your host already gives a request.
  • Your services are in Go.
  • You want to self-host the orchestrator.
  • Your workflows handle protected health information, and your Inngest BAA covers them.

When to choose Render Workflows

  • Individual steps are heavy: long-running model calls, video and image processing, large file parsing, or long scrapes.
  • A step needs more time or memory than your host allows, and you don't want to run and scale a worker fleet for it.
  • You want each task to pick its own compute plan.
  • Your tasks read and write Postgres or a Redis-compatible key-value store, or need private networking between services.
  • You want one compute meter per run, with no separate per-step fee.

How do you use Render Workflows and Inngest together?

Run the orchestration on Inngest and send the heavy steps to Render. An Inngest function can start a Render task and pause without compute until the task sends an event back:

  1. Your app sends a video/uploaded event to Inngest.
  2. An Inngest function starts a Render task with the Render SDK in a step.run() call.
  3. The function calls step.waitForEvent() with match: "data.videoUrl" and a timeout, then pauses.
  4. The Render task runs on the compute plan it needs, writes results to Render Postgres, and sends a video/transcoded event with the same videoUrl to Inngest with the Inngest SDK.
  5. The Inngest function resumes when the matching event arrives and continues with notifications or approvals. If the wait times out, step.waitForEvent() returns null, so handle that case.

If a task can finish in seconds, it might send its event before the wait starts, and Inngest won't resume the run. Use a timeout so the run doesn't hang.

This Inngest function uses the TypeScript SDK v4, which takes triggers in the options object:

In the Render workflow, have the parent task send the video/transcoded event with the Inngest Python SDK after its transcodes finish:

Store RENDER_API_KEY where your Inngest functions run, and store INNGEST_EVENT_KEY in your Render workflow service.

Moving from Inngest to Render Workflows

Each Inngest function becomes a parent Render task. Group step.run() calls into tasks. A short step becomes a ctx.step() call in the parent task, and a step that needs its own retries or compute plan becomes a separate task that the parent calls with ctx.run(). Each step.invoke() call also becomes a ctx.run() call.

Render has no equivalent of step.sleep(), step.sleepUntil(), step.waitForEvent(), or step.waitForSignal(), so split each long wait into two task runs. Start the second run from the code that receives the approval or event, or from a cron job. Replace each step.sendEvent() call with a Render SDK call that starts a task run without waiting for its result.

Replace event triggers by calling the Render SDK from the code that sent the event, and replace cron triggers with Render cron jobs. Render has no built-in throttling or debounce, so enforce those limits in your app before you start a run. Start with the Render Workflows tutorial or run render workflows init to scaffold a project.

Frequently asked questions