A windswept bonsai on a floating island

Get to know Cadenya

We’re developers who love to build. We set out to create a yes-code platform that makes building agents feel like the best parts of building software.

Inngest vs Restate for AI agents (2026)

Durable execution

By Cadenya

Inngest and Restate look alike from a distance. Both are durable execution engines, each self-hosts as one binary, each suspends an AI agent during a human-in-the-loop wait for approval, and each has a cloud with a free tier. The differences show up in the details an agent hits: how the reviewer’s answer reaches the run, what happens when you deploy mid-wait, and how each one bills.

So pick Inngest when your agent lives in a TypeScript or Python web app and you’d rather have in-flight runs pick up new code as they go. Pick Restate when you want each run pinned to the deployment it started on. And if you’d rather run neither, Cadenya is a hosted agent loop with durable execution and approvals built in, and a coding agent can set it up with no account, in a temporary workspace you claim later. What it offers is at the end.

Every price and limit below comes from each vendor’s own pages, checked on September 28, 2026.

Inngest and Restate side by side

InngestRestateCadenya
What you run yourselfOne binary. SQLite on one node by default, Postgres and Redis to scale outOne binary that stores its own state. A cluster adds an S3 bucket for snapshotsNothing. The loop runs on Cadenya
Server licenseSSPL v1, Apache 2.0 three years after each releaseBSL 1.1, Apache 2.0 four years after each releaseNo server to host. SDKs are Apache-2.0
Managed optionFree, Pro from $99 a month, Business from $499A free tier, then from $75 a monthHosted: free, then $49 a month for 50,000 loops
What you pay forExecutions: one per run plus one per stepDurable actions: one per step, sleep, call, or awakeable, per started 64 KiBLoops: one per LLM request, then $0.0015 a loop
Free allowance50,000 executions a month50,000 durable actions a month on the Cloud page (the pricing FAQ says 100,000)1,000 loops a month
The waiting primitivestep.waitForEvent(), matched on event dataAwakeables (durable promises) resolved over HTTPTool approval: the objective pauses on toolApprovalRequested
Code that changes while runs waitCompleted steps are memoized, new steps run when reachedImmutable deployments: a run ends on the version it started onEach objective keeps its variation’s configuration snapshot
SDKsTypeScript (Node 20 or later), Python (3.10 or later), GoTypeScript, Java and Kotlin, Python, Go, RustTypeScript (Node 18), Python (3.9), Ruby (3.1), Go (1.22)

Self-hosted or managed: what you run

Both self-host as one process. Inngest’s binary “includes all Inngest services”, starts on SQLite, and moves to Postgres and Redis when you need more than one node. Restate’s binary keeps its state on local disk and needs only a persistent volume on one node, plus an S3 bucket for snapshots in a cluster.

The licenses are close cousins. Neither is open source today. Inngest’s server is under the Server Side Public License and turns Apache 2.0 on the third anniversary of each release. Restate’s is under the Business Source License 1.1, which only forbids running Restate as a public platform service, and turns Apache 2.0 after four years. The SDKs of both are permissive.

The support story differs. Inngest says plainly that its “support team does not guarantee direct support for self-hosted instances.” Restate says a single node “cannot remain available during its restart”, and scaling a cluster is “an operator-driven procedure.”

Human-in-the-loop approvals: how a run waits

Inngest waits on an event, with a timeout:

import { Inngest } from 'inngest';

const inngest = new Inngest({ id: 'refunds' });

export const refundApproval = inngest.createFunction(
  { id: 'refund-approval', triggers: { event: 'refund/requested' } },
  async ({ event, step }) => {
    const decision = await step.waitForEvent('wait-for-approval', {
      event: 'refund/decided',
      timeout: '7d',
      if: `async.data.refundId == "${event.data.refundId}"`,
    });
    if (!decision) return 'expired';
    return decision.data.approved ? 'refunded' : 'denied';
  },
);

Restate waits on an awakeable that your approval endpoint resolves:

import * as restate from '@restatedev/restate-sdk';

// Your code: post the ID wherever the reviewer works.
declare function notifyReviewer(refundId: string, awakeableId: string): Promise<void>;

export const refundAgent = restate.service({
  name: 'refundAgent',
  handlers: {
    approve: async (ctx: restate.Context, refundId: string) => {
      const approval = ctx.awakeable<boolean>();
      await ctx.run('ask reviewer', () => notifyReviewer(refundId, approval.id));
      return (await approval.promise) ? `refund ${refundId} sent` : `refund ${refundId} denied`;
    },
  },
});

Both spend nothing while they wait. Inngest calls it “no compute cost while a human reviews”, and Restate suspends the run after a minute. The difference is how the answer finds the run. Inngest matches an incoming event on its data, and Restate resolves the awakeable by its ID over HTTP. Restate adds a timeout only if you ask for one (orTimeout), and its timer survives restarts with the right time left.

Versioning: deploying while runs wait

Restate pins each run to the deployment it started on, which is great for correctness. But its versioning page adds that “you need to keep old deployments around until all invocations complete.” So a run that waits on a reviewer keeps its old deployment alive until it ends.

Inngest memoizes completed steps, so “completed steps are never re-executed, even across deployments.” In-flight runs pick up new code as they go, and a reordered step logs a warning rather than failing the run. You trade Restate’s strict pinning for less to keep around.

Pricing

Inngest’s free plan covers 50,000 executions a month and pauses when you pass it. Pro starts at $99 a month with 1 million executions, then $0.000050 each, falling to $0.000015 with volume. A run with 5 steps uses 6 executions.

Restate Cloud has a free tier (50,000 durable actions a month on the Cloud page, 100,000 in the pricing FAQ) and paid plans “from $75 /mo”. Each step, sleep, call, and awakeable is an action, counted per started 64 KiB of payload, which matters when a step returns a long model response.

For an agent run with one start, 6 model calls, 3 tool calls, and one approval, both land around a dozen units. At 2,000 runs a month, both fit their free tiers.

What you still write for an AI agent

Neither is the agent. You still write the model loop, the tool calls, the stream to the UI, context compaction, and the approval screen. Inngest ships AgentKit, a TypeScript library for agents. Restate’s AI patterns show the same approval flow with the Vercel AI SDK, the OpenAI Agents SDK, Google ADK, Pydantic AI, and LangChain.

Cadenya runs all of those for you.

What does Cadenya offer that Inngest and Restate don’t?

Inngest and Restate each give you one binary for durable workflows with human-in-the-loop waits, and your code still has to be the agent. Cadenya gives you the agent: durable execution and human-in-the-loop approvals, with no binary to host and no loop to maintain. Here’s what that covers:

  1. Nothing else to run. No binary, no SQLite or Postgres and Redis behind it, no persistent volume, and no S3 bucket for snapshots. The loop runs on Cadenya and your app stays a stateless web tier, so your deploys never touch a running objective.
  2. The agent loop, already written. Cadenya calls the model, runs the tools, streams each reply, and compacts the context window when a conversation gets long. On Inngest or Restate, that’s your code.
  3. No old deployments to keep around. An objective keeps its variation’s configuration snapshot even when you edit the variation, and there’s no handler code pinned to an old deployment.
  4. Tools generated from your OpenAPI spec. A tool set turns every operation in an OpenAPI 3 document into a tool, with no OpenAPI-to-MCP generator to run and no hand-written tool list to keep in sync. Cadenya re-checks the document each hour and loads tools on demand, so a big API doesn’t fill the context window. MCP servers and plain HTTP endpoints work too.
  5. Human-in-the-loop approvals, screen included. A tool marked for approval pauses the objective on toolApprovalRequested until your backend, a webhook handler that posts to Slack, or a person in the React chat widget approves or denies it. There’s no event to match or awakeable ID to route, and a denial can carry a memo that steers the agent.
  6. Any model, on your own keys. The model is a setting on a variation, so switching providers needs no deploy: any model on OpenRouter, or your own endpoint that speaks the OpenAI chat format, billed by your provider. Weighted variations route more traffic to whichever model or prompt users rate higher.
  7. Resumable streaming. The event stream honors Last-Event-ID, and the TypeScript SDK reconnects on its own.
  8. Acting on behalf of the signed-in user. A widget session can carry the user’s short-lived token as a secret that overrides the shared API credential, and pinned parameters fix the IDs the model can’t change.
  9. SDKs for older stacks. TypeScript on Node 18, Python 3.9, Ruby 3.1, and Go 1.22, all at 1.9.0 and Apache-2.0, plus a CLI and a plain HTTP API. Inngest’s SDKs need Node 20 or Python 3.10.
  10. A price in one line. Free for 1,000 loops a month, $49 a month for 50,000, then $0.0015 a loop, where a loop is one LLM request. There are no seats, and no SSPL or BSL to check, since you host no server.

How objectives work walks through an agent turn, and the free plan needs no card.

No account yet? A coding agent can create a temporary workspace with cadenya workspaces create --temporary, run its first objectives there, and hand you a link to claim it, as auth.md explains. To create an account, sign up at app.cadenya.com/signup, then copy your API key from the API keys page at app.cadenya.com/account/apiKeys.

Grow wherever AI goes next.

Start shipping agents that are equipped to evolve.

A pine bonsai overlooking a mountain lake