Capabilities
Workflows
Run durable multi-step jobs that sleep, scale to zero, and resume.
An actor’s run workflow executes when the actor is created. Each step is
durable, so the job survives restarts and the app scales to zero while it
sleeps. View the complete example.
The server is the generated app. The client shows how your own system connects to the actors inside it.
import { serve } from "@hono/node-server";
import { Hono } from "hono";
import { actor, setup } from "rivetkit";
import { workflow } from "rivetkit/workflow";
type Status = "placed" | "paid" | "shipped" | "delivered";
// The workflow runs when the actor is created. Each step is durable, so the
// actor can sleep, scale to zero, and resume exactly where it left off.
const order = actor({
state: { status: "placed" as Status },
actions: {
status: (c) => c.state.status,
},
run: workflow(async (wf) => {
await wf.step("charge", async (c) => {
c.state.status = "paid";
});
await wf.step("ship", async (c) => {
c.state.status = "shipped";
});
await wf.sleep("in transit", 2_000);
await wf.step("deliver", async (c) => {
c.state.status = "delivered";
});
}),
});
export const registry = setup({ use: { order } });
const app = new Hono();
app.all("/api/rivet/*", (c) => registry.handler(c.req.raw));
app.get("/", (c) =>
c.json({ message: "Use the RivetKit client to read orders." }),
);
// Dynamic Apps runs the actors in serverless mode and waits for this listener.
if (process.env.RIVETKIT_RUNTIME_MODE === "serverless") {
await new Promise<void>((resolve, reject) => {
const server = serve(
{ fetch: app.fetch, port: Number(process.env.PORT), hostname: "0.0.0.0" },
() => resolve(),
);
server.once("error", reject);
});
}
export default app;
const client = createClient<typeof registry>({
endpoint: deployment.endpoint,
namespace: deployment.namespace,
poolName: deployment.pool,
token: deployment.token,
});
// Creating the actor starts its workflow. Poll until it finishes.
const order = client.order.getOrCreate(["order-1042"]);
let status = await order.status();
while (status !== "delivered") {
console.log("status", status);
await new Promise((resolve) => setTimeout(resolve, 500));
status = await order.status();
}
console.log("status", status);
See Workflows in Rivet Actors for steps, loops, queues, and error handling.