megachangelog
Feature

Call Workflows declared in exports through ctx.exports

Workers can now call Workflows declared in their Wrangler configuration exports field through ctx.exports, eliminating the need for a separate workflows binding. Workflows are keyed by class name and share the same API as bindings, with local development support via Wrangler, Vite, and Vitest plugins.

A Worker can now call the Workflows it declares in the exports field of its Wrangler configuration through ctx.exports. You no longer need a workflows binding to call a Workflow from the Worker that defines it.

Each Workflow is keyed by class name, and has the same API as a Workflow binding:

src/index.jsjs
export default {
	async fetch(request, env, ctx) {
		const instance = await ctx.exports.MyWorkflow.create({
			params: { name: "World" },
		});
		return Response.json({ id: instance.id });
	},
};
src/index.tsts
export default {
	async fetch(request, env, ctx): Promise<Response> {
		const instance = await ctx.exports.MyWorkflow.create({
			params: { name: "World" },
		});
		return Response.json({ id: instance.id });
	},
} satisfies ExportedHandler<Env>;

A workflows binding and a workflow export with the same name share their instances. You can move a Workflow from a binding to an export without losing its instances.

wrangler dev, the Cloudflare Vite plugin, and the Workers Vitest integration run Workflows on ctx.exports locally. Local development requires Wrangler 4.142.0, @cloudflare/vite-plugin 1.61.0, or @cloudflare/vitest-plugin 1.3.0 or above.

In Vitest, introspectWorkflow() and introspectWorkflowInstance() still need a Workflow binding. To introspect a Workflow declared in exports, add a test-only binding to it.

For more information, refer to Call a Workflow through ctx.exports.

workersworkflowsapidevelopment

Source: original entry ↗