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 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 long a run may wait, what happens when you deploy mid-wait, and which languages you can write it in.
So pick Inngest when your agent lives in a TypeScript or Python web app and waits are measured in days. Pick Restate when you want Java, Kotlin, or Rust, or you’d rather state no wait limit at all. And if you’d rather run neither, Cadenya is a hosted agent loop with durable execution and approvals built in. 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
| Inngest | Restate | |
|---|---|---|
| What you run yourself | One binary. SQLite on one node by default, Postgres and Redis to scale out | One binary that stores its own state. A cluster adds an S3 bucket for snapshots |
| Server license | SSPL v1, Apache 2.0 three years after each release | BSL 1.1, Apache 2.0 four years after each release |
| Managed option | Free, Pro from $99 a month, Business from $499 | A free tier, then from $75 a month |
| What you pay for | Executions: one per run plus one per step | Durable actions: one per step, sleep, call, or awakeable, per started 64 KiB |
| Free allowance | 50,000 executions a month | 50,000 durable actions a month on the Cloud page (the pricing FAQ says 100,000) |
| How long a run can wait for a person | Until its waitForEvent timeout, inside a maximum run length of 30 days (Free) to 366 days (Pro) | No stated limit. The run suspends after a minute of waiting |
| The waiting primitive | step.waitForEvent(), matched on event data | Awakeables (durable promises) resolved over HTTP |
| Code that changes while runs wait | Completed steps are memoized, new steps run when reached | Immutable deployments: a run ends on the version it started on |
| SDKs | TypeScript (Node 20 or later), Python (3.10 or later), Go | TypeScript, Java and Kotlin, Python, Go, Rust |
| Compliance on the managed option | HIPAA on the Enterprise plan | SOC 2, HIPAA BAA |
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 long a run can wait
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. So which one waits longer? The difference is the ceiling. Inngest returns null at the timeout and caps the whole run by plan. Restate’s human-in-the-loop page 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
This is where Restate’s “no limit” meets a practical one. Restate pins each run to the deployment it started on, which is great for correctness. But its versioning page says to “Avoid long-running handlers (days or months)”, because “you need to keep old deployments around until all invocations complete.” A reviewer who takes a week keeps last week’s deployment alive for a week.
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 (its latest release, 0.13.2, dates from November 2025). 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:
- 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.
- 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.
- 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 last week’s deployment.
- 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.
- Human-in-the-loop approvals, screen included. A tool marked for approval pauses the objective on
toolApprovalRequesteduntil 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. - 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.
- Resumable streaming. The event stream honors
Last-Event-ID, and the TypeScript SDK reconnects on its own. - 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.
- SDKs for older stacks. TypeScript on Node 18, Python 3.9, Ruby 3.1, and Go 1.22, all at 1.7.0 and Apache-2.0, plus a CLI and a plain HTTP API for Java or anything else. Inngest’s SDKs need Node 20 or Python 3.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.
Grow wherever AI goes next.
Start shipping agents that are equipped to evolve.