Skip to main content
Workloads

Workflows

Run durable multi-step jobs that survive restarts and scale to zero while they sleep.

Prefer to read code? Clone the example repository. View on GitHub

Example generated code

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." }),
);

export default app;

Deploy and connect

Deploy the app, then connect to its actors from your own system:

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.