Introducing Dynamic Workflows: durable execution that follows the tenant Cloudflare has introduced Dynamic Workflows, a new feature that bridges durable execution with dynamic deployment, allowing platforms to run tenant-specific workflow code that is loaded at runtime rather than being part of the initial deployment. The solution uses a small TypeScript library called `@cloudflare/dynamic-workflows`, which enables a single Worker Loader to route workflow creation and execution calls to different tenant code, even when execution occurs hours or days later. This addresses the limitation of traditional Workflows, which required workflow code to be defined at deploy time, making it unsuitable for multi-tenant applications where each customer has unique business logic. When we first launched Workers eight years ago, it was a direct-to-developers platform. Over the years, we have expanded and scaled the ecosystem so that platforms could not only build on Workers directly, but they could also enable their customers to ship code to us through many multi-tenant applications. We now see on Workers: Applications where users describe what they want, and the AI writes the implementation. Multi-tenant SaaS where every customer's business logic is, at runtime, some TypeScript the platform has never seen before. Agents that write and run their own tools. CI/CD products where every repo defines its own pipeline. Last month, when we shipped the Dynamic Workers open beta , we gave those platforms a clean primitive for the compute side: hand the Workers runtime some code at runtime, get back an isolated, sandboxed Worker, on the same machine, in single-digit milliseconds. Durable Object Facets extended the same idea to storage — each dynamically-loaded app can have its own SQLite database, spun up on demand, with the platform sitting in front, as a supervisor. Artifacts did the same for source control : a Git-native, versioned filesystem you can create by the tens of millions, one per agent, one per session, one per tenant. So, we have dynamic deployment for storage and source control. What’s next? Today, we are bridging durable execution and dynamic deployment with Dynamic Workflows . The gap between durable and dynamic execution Cloudflare Workflows is our durable execution engine. It turns a run event, step function into a program where every step survives failures, can sleep for hours or days, can wait for external events, and resumes exactly where it left off when the isolate is recycled. It's the right primitive for anything that has to "keep going" past a single request: onboarding flows, video transcoding pipelines, multi-stage billing, long-running agent loops, and — as of Workflows V2 — up to 50,000 concurrent instances and 300 new instances per second per account, redesigned for the agentic era. But Workflows has always had one assumption baked in: the workflow code is part of your deployment. Your wrangler.jsonc has a block that says "when the engine calls into WORKFLOWS , run the class called MyWorkflow ." One binding, one class. Per deploy. That works fine if you own all the code. It's fine if you're running a traditional application. It stops working the moment you want to let your customer ship their workflow. Say you're building an app platform where the AI writes TypeScript for every tenant. Say you're running a CI/CD product where each repository has its own pipeline. Say you're using an agents SDK where each agent writes its own durable plan. In every one of these cases, the workflow is different for every tenant, every agent, every request. There is no single class to bind. This is the same shape of problem that Dynamic Workers solved for compute and that Durable Object Facets solved for storage. We just hadn't solved it for durable execution yet. @cloudflare/dynamic-workflows is a small library. Roughly 300 lines of TypeScript. It lets a single Worker — the Worker Loader — route every create call to a different tenant's code, and, critically, have the Workflows engine dispatch run event, step back to that same code when the workflow actually executes, seconds or hours or days later. Here's the whole pattern. A Worker Loader: js import { createDynamicWorkflowEntrypoint, DynamicWorkflowBinding, wrapWorkflowBinding, } from '@cloudflare/dynamic-workflows'; // The library looks this class up on cloudflare:workers exports. export { DynamicWorkflowBinding }; function loadTenant env, tenantId { return env.LOADER.get tenantId, async = { compatibilityDate: '2026-01-01', mainModule: 'index.js', modules: { 'index.js': await fetchTenantCode tenantId }, // The tenant sees this as a normal Workflow binding. env: { WORKFLOWS: wrapWorkflowBinding { tenantId } }, } ; } // Register this as class name in wrangler.jsonc. export const DynamicWorkflow = createDynamicWorkflowEntrypoint