What is Inngest?
Durable functions for agents and workflows, with isolated code execution, live progress, and outcome scoring built in.
Inngest makes your code durable. You write functions in your existing app and break the work into steps. Inngest runs each step, saves its result, and retries failed work from the step that failed. Every run has a trace that shows what ran, what waited, and what failed.
The rest of the platform builds on the same run. Sandboxes run code in isolation inside it, Realtime streams its progress to users, and Agent Evals connect later feedback to it. Together, they let you see what ran, recover from failures, run untrusted code safely, and measure whether each change actually helped.
An example run
A support agent answers a customer ticket. The same pattern works for background jobs, data pipelines, and other workflows.
Here's that function in TypeScript. Each step.run() is saved, so a failed reply retries without reloading context or redrafting the answer. group.experiment() picks the answer strategy, step.realtime.publish() updates the customer, and step.sandbox runs diagnostics in an isolated VM. When the customer rates the answer days later, a deferred scorer credits that rating to the chosen variant.
const ticketChannel = realtime.channel({
name: ({ ticketId }: { ticketId: string }) => `ticket:${ticketId}`,
topics: { status: { schema: z.object({ message: z.string() }) } },
});
export const answerTicket = inngest.createFunction(
{ id: "answer-ticket", triggers: { event: "support/ticket.created" } },
async ({ event, step, group }) => {
const { ticketId } = event.data;
const channel = ticketChannel({ ticketId });
// Each step's result is saved. A retry skips steps that already finished.
const context = await step.run("load-context", () =>
loadTicketContext(ticketId)
);
// Pick variant A or B, then draft the answer with that strategy.
const { result: answer } = await group.experiment("answer-style", {
variants: {
concise: () =>
step.run("draft-concise", () => draftAnswer(context, "concise")),
detailed: () =>
step.run("draft-detailed", () => draftAnswer(context, "detailed")),
},
select: experiment.weighted({ concise: 50, detailed: 50 }),
});
// Stream progress to the customer's browser.
await step.realtime.publish("drafted", channel.status, {
message: "Checking your account…",
});
// Run diagnostics in an isolated Sandbox.
const sandbox = await step.sandbox.create("create-sandbox", {
name: `diagnose-${ticketId}`,
vcpu: 1,
memoryMb: 1024,
});
const diagnostics = await sandbox.commands.run(
"run-diagnostics",
"./diagnose.sh",
{ timeout: "30s" }
);
await sandbox.destroy("destroy-sandbox");
await step.run("send-reply", () =>
sendReply(ticketId, `${answer}\n\n${diagnostics.stdout}`)
);
}
);How Inngest works
Durable Execution
An event, schedule, or API request starts a run. Inngest records completed steps, resumes after waits, retries failed work from where the function left off, and controls how much work runs at once. In the example, if the reply fails to send, only that step runs again.
- Events and triggers start work from events, schedules, webhooks, or another function.
- Steps save progress so retries skip completed work.
- Retries recover failed work automatically.
- Wait for events or sleep until later without keeping compute running.
- Flow control limits concurrency and throughput to protect downstream services.
- Idempotency prevents duplicate events from repeating work.
Use durable functions as background workflows or as durable endpoints that return an HTTP response.
Sandboxes
When a step needs its own execution environment, such as to run generated code or test a repository, run that work in a Sandbox. Each Sandbox is a microVM with its own filesystem and processes, isolated from your app and other Sandboxes. You can pause and resume a Sandbox, or snapshot it and clone a new one. Sandbox activity appears in the same run trace as the surrounding steps. In the example, the agent runs a diagnostic script in a Sandbox before it replies.
Sandboxes run code inside a run. They aren't a way to host your Inngest functions. Read Sandboxes for lifecycle, isolation, and cleanup details.
Agent Evals
A run can succeed and still fail to help the customer. Agent Evals connect outcome scores to the runs that produced them, so you can judge changes by their results:
- Sessions group related runs, such as every run for one ticket.
- Scores record a named number or true/false value for a run or step. Score right away, or defer the score until feedback arrives. A deferred score is credited to the original run.
- Experiments use
group.experiment()to select a variant for each run. A variant can be one step or a whole workflow path. Pass the experiment reference with a score so a later outcome counts toward the variant that produced it.
In the example, the customer's rating arrives days later. It's scored against the original run and its variant, so you can compare answer strategies, then open traces to see how each result was produced.
Realtime
Realtime sends typed messages from a function to authorized clients, so users can follow work as it runs. Use step.realtime.publish() for state changes and final results so a retry doesn't send the message twice. Use inngest.realtime.publish() for frequent updates such as token streams. In the example, the customer sees the agent's progress while it drafts an answer.
Where your code runs
Your functions run on your own infrastructure, in any cloud or on your servers. Inngest calls them through an HTTP serve() endpoint, or they connect to Inngest as a Connect worker. Inngest coordinates durable execution while your code runs where it already lives. Use Inngest Cloud, or self-host Inngest.
Sandboxes are different: they run on securely isolated VMs that Inngest manages, so you don't host or scale that infrastructure yourself. Your function starts and controls them as steps in its run.
Explore the platform
Durable Execution
Coordinate steps, retries, waits, and events so work finishes after failures.
Sandboxes
Run code in isolated microVMs as part of a durable run.
Agent Evals
Score outcomes and compare changes to steps and workflows.
Realtime
Stream progress from durable runs to your users.
Flow control
Control concurrency, throughput, and fairness across tenants.
Observability
Inspect traces, replay runs, and track metrics in production.
Start building
Pick your language to build your first durable function. Use Local Development to run and inspect it on your machine with the Dev Server.
TypeScript
Works with Node.js, Bun, Deno, and edge runtimes.
Python
Sync and async functions with FastAPI, Flask, or Django.
Go
Typed events and durable steps with the standard library.
Or start from your framework:
Next steps
- Concepts defines runs, triggers, steps, waits, and retries.
- Glossary explains the terms used across the docs.
- Deploying functions compares HTTP serving and Connect.
- Platform and operations covers traces, replay, environments, and keys.