Workflows, Workers - Call Workflows declared in `exports` through `ctx.exports`
- Announced
- Tags
- Workflows, Workers
- Severity
- info, set by
reef/rss-rule-v1 - Source
- https://developers.cloudflare.com/changelog/post/2026-09-27-workflow-ctx-exports/
<p>A Worker can now call the Workflows it declares in the <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#workflow-exports"><code>exports</code></a> field of its Wrangler configuration through <a href="https://developers.cloudflare.com/workers/runtime-apis/context/#exports"><code>ctx.exports</code></a>. You no longer need a <code>workflows</code> binding to call a Workflow from the Worker that defines it.</p> <p>Each Workflow is keyed by class name, and has the same API as a Workflow binding:</p> <div><div data-nb-tabs data-nb-sync-key="workersExamples" class><div class="relative flex border-b border-border" role="tablist" data-nb-tabs-list><span class="bg-primary pointer-events-none absolute -bottom-px h-0.5 rounded-t-sm transition-[left,width] duration-200 ease-out" data-nb-tabs-indicator aria-hidden="true"></span></div><div class="mt-3"><div role="tabpanel" data-nb-tabs-content data-nb-tab-label="JavaScript" class><figure class="nb-code-figure nb-code-figure-titled" data-nb-lang="js"><figcaption class="nb-code-title"><span class="nb-code-title-name">src/index.js</span><span class="nb-code-title-lang">js</span></figcaption><pre class="astro-code astro-code-themes github-light github-dark nb-shiki-c6xiwz" tabindex="0" data-language="js" data-nb-lang="js"><code><span class="line"><span class="nb-shiki-1itgoe">export</span><span class="nb-shiki-1itgoe"> default</span><span class="nb-shiki-140thh"> {</span></span> <span class="line"><span class="nb-shiki-1itgoe"> async</span><span class="nb-shiki-1t8gfj"> fetch</span><span class="nb-shiki-140thh">(</span><span class="nb-shiki-1jdh33">request</span><span class="nb-shiki-140thh">, </span><span class="nb-shiki-1jdh33">env</span><span class="nb-shiki-140thh">, </span><span class="nb-shiki-1jdh33">ctx</span><span class="nb-shiki-140thh">) {</span></span> <span class="line"><span class="nb-shiki-1itgoe"> const</span><span class="nb-shiki-dzsirb"> instance</span><span class="nb-shiki-1itgoe"> =</span><span class="nb-shiki-1itgoe"> await</span><span class="nb-shiki-140thh"> ctx.exports.MyWorkflow.</span><span class="nb-shiki-1t8gfj">create</span><span class="nb-shiki-140thh">({</span></span> <span class="line"><span class="nb-shiki-140thh"> params: { name: </span><span class="nb-shiki-mdbnqw">"World"</span><span class="nb-shiki-140thh"> },</span></span> <span class="line"><span class="nb-shiki-140thh"> });</span></span> <span class="line"><span class="nb-shiki-1itgoe"> return</span><span class="nb-shiki-140thh"> Response.</span><span class="nb-shiki-1t8gfj">json</span><span class="nb-shiki-140thh">({ id: instance.id });</span></span> <span class="line"><span class="nb-shiki-140thh"> },</span></span> <span class="line"><span class="nb-shiki-140thh">};</span></span></code></pre></figure></div><div role="tabpanel" data-nb-tabs-content data-nb-tab-label="TypeScript" class><figure class="nb-code-figure nb-code-figure-titled" data-nb-lang="ts"><figcaption class="nb-code-title"><span class="nb-code-title-name">src/index.ts</span><span class="nb-code-title-lang">ts</span></figcaption><pre class="astro-code astro-code-themes github-light github-dark nb-shiki-c6xiwz" tabindex="0" data-language="ts" data-nb-lang="ts"><code><span class="line"><span class="nb-shiki-1itgoe">export</span><span class="nb-shiki-1itgoe"> default</span><span class="nb-shiki-140thh"> {</span></span> <span class="line"><span class="nb-shiki-1itgoe"> async</span><span class="nb-shiki-1t8gfj"> fetch</span><span class="nb-shiki-140thh">(</span><span class="nb-shiki-1jdh33">request</span><span class="nb-shiki-140thh">, </span><span class="nb-shiki-1jdh33">env</span><span class="nb-shiki-140thh">, </span><span class="nb-shiki-1jdh33">ctx</span><span class="nb-shiki-140thh">)</span><span class="nb-shiki-1itgoe">:</span><span class="nb-shiki-1t8gfj"> Promise</span><span class="nb-shiki-140thh"><</span><span class="nb-shiki-1t8gfj">Response</span><span class="nb-shiki-140thh">> {</span></span> <span class="line"><span class="nb-shiki-1itgoe"> const</span><span class="nb-shiki-dzsirb"> instance</span><span class="nb-shiki-1itgoe"> =</span><span class="nb-shiki-1itgoe"> await</span><span class="nb-shiki-140thh"> ctx.exports.MyWorkflow.</span><span class="nb-shiki-1t8gfj">create</span><span class="nb-shiki-140thh">({</span></span> <span class="line"><span class="nb-shiki-140thh"> params: { name: </span><span class="nb-shiki-mdbnqw">"World"</span><span class="nb-shiki-140thh"> },</span></span> <span class="line"><span class="nb-shiki-140thh"> });</span></span> <span class="line"><span class="nb-shiki-1itgoe"> return</span><span class="nb-shiki-140thh"> Response.</span><span class="nb-shiki-1t8gfj">json</span><span class="nb-shiki-140thh">({ id: instance.id });</span></span> <span class="line"><span class="nb-shiki-140thh"> },</span></span> <span class="line"><span class="nb-shiki-140thh">} </span><span class="nb-shiki-1itgoe">satisfies</span><span class="nb-shiki-1t8gfj"> ExportedHandler</span><span class="nb-shiki-140thh"><</span><span class="nb-shiki-1t8gfj">Env</span><span class="nb-shiki-140thh">>;</span></span></code></pre></figure></div></div></div><script type="module" src="https://developers.cloudflare.com/home/runner/work/cloudflare-docs/cloudflare-docs/src/components/ui/tabs/Tabs.astro?astro&type=script&index=0&lang.ts"></script></div> <p>A <code>workflows</code> binding and a <code>workflow</code> export with the same <code>name</code> share their instances. You can move a Workflow from a binding to an export without losing its instances.</p> <p><code>wrangler dev</code>, the <a href="https://developers.cloudflare.com/workers/vite-plugin/">Cloudflare Vite plugin</a>, and the <a href="https://developers.cloudflare.com/workers/testing/vitest-integration/">Workers Vitest integration</a> run Workflows on <code>ctx.exports</code> locally. Local development requires Wrangler 4.142.0, <code>@cloudflare/vite-plugin</code> 1.61.0, or <code>@cloudflare/vitest-plugin</code> 1.3.0 or above.</p> <p>In Vitest, <code>introspectWorkflow()</code> and <code>introspectWorkflowInstance()</code> still need a Workflow binding. To introspect a Workflow declared in <code>exports</code>, add a <a href="https://developers.cloudflare.com/workers/testing/vitest-integration/test-apis/#introspect-workflows-declared-in-exports">test-only binding</a> to it.</p> <p>For more information, refer to <a href="https://developers.cloudflare.com/workflows/build/workers-api/#call-a-workflow-through-ctxexports">Call a Workflow through <code>ctx.exports</code></a>.</p>
The text above is the source's. reef added the severity, the dates it could read from the text, and the endpoints and scopes named in code.