Cloudflare has released Dynamic Workflows, an MIT-licensed library that extends the company's durable execution engine so that workflow code can be different for every tenant, agent, or request at runtime.
Previously, Cloudflare Workflows required workflow code to be part of the deployment, one binding, one class, per deploy. Dynamic Workflows removes that constraint, letting a platform route every create() call to a different tenant's code and have the engine dispatch run(event, step) back to that same code when the workflow executes seconds, hours, or days later. Dan Lapid and Luís Duarte from the Cloudflare engineering team write:
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.
The library is roughly 300 lines of TypeScript. A Worker Loader sits between the Workflows engine and the tenant's code (a Dynamic Worker), routing execution to the right tenant when the engine wakes up. When a tenant calls env.WORKFLOWS.create(...), it looks like a normal Workflow binding. Behind the scenes, the Worker Loader wraps the call with tenant metadata, the Workflows engine persists the payload, and when the engine later wakes to execute a step, the metadata routes execution back to the correct tenant's code. Workflow IDs, pause/resume, retries, hibernation, step.sleep('24 hours'), and step.waitForEvent() all work unchanged.
import { createDynamicWorkflowEntrypoint, DynamicWorkflowBinding, wrapWorkflowBinding } from '@cloudflare/dynamic-workflows';
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) },
env: { WORKFLOWS: wrapWorkflowBinding({ tenantId }) },
}));
}
export const DynamicWorkflow = createDynamicWorkflowEntrypoint(
async ({ env, metadata }) => {
const stub = loadTenant(env, metadata.tenantId);
return stub.getEntrypoint('TenantWorkflow');
}
);
The CI/CD use case is where the architectural implications become most concrete. The blog post walks through a complete pipeline where the pipeline code lives in the customer's repository as a TypeScript WorkflowEntrypoint. The platform loads it dynamically, and each step runs with full durable execution semantics. The post lines up four Cloudflare primitives working together: Artifacts provides Git-native versioned storage with lazy tree hydration and instant fork() per CI run. Dynamic Workers run lightweight steps (lint, typecheck, bundle) in sandboxed isolates that boot in milliseconds. Dynamic Workflows hold the run together with durable, retryable steps that hibernate for free during approval waits. And Sandboxes handle the heavy steps that need a full operating system, with snapshot-based warm starts in seconds.
Cloudflare contrasts this with the ceremony of traditional CI, where allocating a VM, pulling a base image, cloning the repo, and installing dependencies can burn a minute or more before any actual work begins. The Dynamic Workflows stack skips all of that ceremony because the repo doesn't move, and the compute comes to it.
The broader platform thesis is explicit. Dynamic Workers solved the compute layer for multi-tenant dynamic code. Durable Object Facets solved the storage layer by giving each dynamically-loaded app its own isolated SQLite database. Dynamic Workflows now solves the durable execution layer. Cloudflare states that every binding Workers currently exposes is heading for a dynamic counterpart: queues, caches, databases, AI bindings, and MCP servers will all eventually be dispatchable per tenant, per agent, per request, at zero idle cost. If realized, this collapses the infrastructure cost of running a multi-tenant platform dramatically: idle tenants cost approximately nothing, active tenants share hardware through isolate-level multi-tenancy. In Cloudflare's framing, a platform that used to cap at thousands of paying customers can now reasonably serve tens of millions.
For agent platforms specifically, Dynamic Workflows means an agent can literally write its own run(event, step) function as a durable plan, where every step is independently retryable, every sleep hibernates for free, and every waitForEvent pauses indefinitely for human approval. The agent writes the plan. The platform runs it. Neither needs to know ahead of time what the plan looks like.
The competitive context for per-tenant durable execution is thin. Temporal and Inngest provide durable execution engines, but neither offers the dynamic per-tenant code loading at the isolation level that Dynamic Workflows enables. AWS Step Functions supports dynamic state machines but requires pre-defined task definitions. The combination of runtime code loading, V8 isolate-level isolation, and edge distribution is currently unique to Cloudflare's stack.
@cloudflare/dynamic-workflows is available on npm now, built on top of Dynamic Workers (open beta on the Workers Paid plan). The repository includes a working example with an interactive browser playground.