Start here
A workflow is a log you can replay.
A Workflow SDK v5 World built on Cloudflare Workers, Durable Objects and R2. Here is what runs where, why each part exists, and what the measurements actually show.
Your workflow code describes the work. The SDK decides how to execute, suspend and replay it. The World supplies durable storage and message delivery. This implementation puts those pieces in your Cloudflare account, without using the Cloudflare Workflows product.
The diagram shows retained-executor mode. Without a dispatch binding, the consumer runs the flow in the main Worker instead.
Same SDK, different infrastructure
A World is an adapter, not a second workflow language. Ordinary "use workflow" and "use step" functions still compile with the published Workflow SDK. The SDK owns deterministic replay, step behavior, hooks and sleeps. Our World implements the interfaces those features call.
export async function order(id: string) {
"use workflow";
const receipt = await charge(id);
await sendReceipt(receipt);
return receipt;
}
async function charge(id: string) {
"use step";
// Call your payment API with a stable idempotency key.
return { id, paid: true };
}The durable record is the event log. After an interruption, core reconstructs workflow decisions from that log. A step result already in history is read back instead of running the body again as part of replay. A retried step attempt can still repeat an external side effect.
Three jobs, kept separate
| Job | Our implementation | Why separate it? |
|---|---|---|
| Remember | Store shards commit events and materialized state to SQLite. Large bytes go to R2. | A workflow survives the request and the process that started it. |
| Deliver | Queue shards persist starts, continuations, delays and retries. | The caller can disconnect without owning the run’s progress. |
| Execute | Runners call the SDK flow handler, optionally in a retained executor Worker. | Workflow CPU and slow I/O do not run on the queue object itself. |
The World client is a library in the caller, not another deployed service. Indexes, token registries and streams support those three jobs; they are not all separate Worker deployments either.
Recorded results, not promises
Run creations
100k burst, build 8cddcbdSequential steps in one run
QuickJS, build adff891Encoded stream chunk cap
Raw allowance depends on framingCurrent probes passed 30k parallel steps on QuickJS and 2.5k native; 35k and 3k respectively hit executor memory limits. The SDK also exhausted memory while reading 2 GiB in one step. The benchmarks page gives the workload, failures and limits of those conclusions.
Read the system in order
From start() through queue delivery, step execution, replay and completion.
Meet every serviceResponsibilities, storage, routing and the trade-off each component introduces.
Compare with VercelThe same SDK contract, two infrastructure designs. Public source only.
Run it yourselfBuild, configure, deploy, test and keep old executors available.
Sources and implementation
Repository links may require access. Vercel links point to public source or published documentation. Logical API names do not establish backend internals.