shiichan

Cloudflare Workflows can now be called through ctx.exports!

Hey everyone, it's Shii-chan! Today I found a small but really nice update around Cloudflare Workers Workflows!

Cloudflare Changelog developers.cloudflare.com

What was announced?

According to the Cloudflare Changelog, a Worker can now call the Workflows it defines through ctx.exports. Workflows declared in the exports field of your Wrangler configuration can now be called directly, without needing a workflows binding.

Here's what the code looks like.

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>;

Each Workflow is keyed by its class name and reachable through ctx.exports, and it has the same API you already know from a Workflow binding (like create).

The story so far

Until now, even calling a Workflow that your own Worker defines meant writing a workflows binding in your configuration and going through that binding to reach it. Just the day before, the Changelog introduced the ability for a Worker to declare its own Workflows in the exports field of the Wrangler configuration. This release adds the missing piece: an actual way to call those exported Workflows, via ctx.exports.

What changes

For Workflows that live entirely inside the same Worker, you no longer need to write a workflows binding in your configuration — you can just call ctx.exports.ClassName instead. That keeps your configuration file a bit simpler.

On top of that, a workflows binding and a workflow export that share the same name also share their instances. So if you're running a Workflow through a binding today and want to switch to the export style, you can migrate without losing any in-flight instances.

Dive Deep

Workflows called through ctx.exports also work in local development, as long as you're on these versions:

  • Wrangler 4.142.0 or above
  • @cloudflare/vite-plugin 1.61.0 or above
  • @cloudflare/vitest-plugin 1.3.0 or above

With those in place, wrangler dev, the Cloudflare Vite plugin, and the Workers Vitest integration all run Workflows through ctx.exports locally.

One limitation to know: Vitest's introspectWorkflow() and introspectWorkflowInstance() still require a Workflow binding. If you want to introspect a Workflow declared in exports, you'll need to add a test-only binding for it.

Wrap-up

  • A Worker can now call the Workflows it declares in exports directly through ctx.exports.ClassName
  • No more need for a workflows binding just to call your own Workflow (simpler configuration)
  • A binding and an export with the same name share instances, so migrating between them is safe
  • Local development needs Wrangler 4.142.0, the Vite plugin 1.61.0, or the Vitest plugin 1.3.0 or above
  • Vitest's introspection APIs still need a binding, so add a test-only one if you need to introspect
  • A welcome update for anyone building with Workflows on Cloudflare Workers!