World / Cloudflare
GitHub

Start here

The architecture

An ordered store for each run, delivery capacity shared across shards, and execution kept off the queue objects.

One run, on CloudflareClick a service to explore itSwipe to explore →
The Cloudflare World’s request and execution pathsThe app reaches a router, which writes to a store shard. Store outbox messages reach queue shards. Runners call the consumer and selected executor. The executor reads and writes run state, streams and snapshots.Your appstart()Router Workerstateless entry pointStore shardsSQLite · ordered eventsQueue shardsreplays / stepsRunnersreplay & step deliveryConsumerdeployment routingExecutor WorkerSDK + workflow bundleRun streams + R2bytes / snapshotsIndex & token shardslists / hook lookup
The app calls start(). The store commits run state and durable publish intent; a queue shard accepts the start. Listing updates happen separately.
Selected pathOther callsLogical components, not individual machines

A box represents a responsibility. Several boxes are different uses of the same Durable Object class. An arrow is a logical call path, not a guarantee about a machine, data center or isolate.

Where everything lives

Deployment or resourceWhat lives there
Main WorkerExample HTTP routes, World adapter, queue consumer and Durable Object class exports. The dispatcher entry point excludes the workflow bundle.
WORLD_STORE namespaceRun stores, token registries and listing indexes, all backed by WorldStore objects with distinct names.
QUEUE_SHARD namespaceDurable queue shards implemented with SQLite and durability. This is not the Cloudflare Queues product.
RUNNER namespaceShared workflow runners and step runners. A run deterministically reaches its workflow runner.
RUN_STREAMS namespaceAn object per run for stream metadata, chunk references and VM snapshot parts.
R2 bucketsPAYLOADS for large values and chunks; DLQ for exhausted queue messages.
Optional WFP namespaceRelease-specific executor Workers, reached by private dispatch and sharing the World’s state bindings.

You do not deploy a database server or broker. Cloudflare operates the platform, but you still own the queue implementation, shard configuration, release routing and operational policies.

Order state, distribute execution

All events for a run land in one store shard. That gives the World one place to check event ordering, step transitions, hook claims and terminal state. SQLite commits the event and the state it changes together.

Different runs spread across many stores. A large fan-out spreads queued steps across queue shards and step runners, while their outcomes still return to the run’s ordered store. This is why adding shards helps many runs but does not remove the bottleneck of one very large run.

One run’s ordered store
Many queued steps
Parallel execution requests
Results back to the same store

Routing without a global directory

The run ID includes a ULID timestamp. That time selects a shard epoch, and the run ID hash selects a store within it. The caller can compute the destination without consulting a central service.

Hook resumes are different: callers may only know a token. A token hash selects a registry in the first epoch, and that registry identifies the owning run. Lists use a third path: store outboxes push compact rows to index shards.

What the design buys, and costs

ChoiceBenefitCost
Warm shared storesAvoid a fresh named store object for every creation.Runs share a store’s CPU and memory budget.
Separate delivery lanesAn open replay delivery does not consume the step lane.More delivery and recovery logic to maintain.
Outbox-fed indexesCreation need not wait for every list index.Lists are eventually consistent; backfill can be expensive.
Retained executorsOld runs can target the code they started with.You must retain scripts, routes and compatible RPC methods.
QuickJS snapshotsSkip much of the earlier replay work.Snapshot compatibility, memory and SDK coupling matter.

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.

Browse topics or type to search

IntroductionA 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.Same SDK, different infrastructureA workflow is a log you can replay.Three jobs, kept separateA workflow is a log you can replay.Recorded results, not promisesA workflow is a log you can replay.Read the system in orderA workflow is a log you can replay.The architectureAn ordered store for each run, delivery capacity shared across shards, and execution kept off the queue objects.Where everything livesThe architectureOrder state, distribute executionThe architectureRouting without a global directoryThe architectureWhat the design buys, and costsThe architectureLife of a requestFollow the ordinary static-workflow start path, then the deliveries that turn the stored intent into completed work.Our World: accepting the runLife of a requestOur World: delivering and runningLife of a requestVercel: the corresponding pathLife of a requestWhat a response does and does not guaranteeLife of a requestEvery service, explainedWhat each component owns, why it exists, how it helps, and the limit it introduces. These are logical roles, not twelve separate deployed services.Router Worker and World clientEvery service, explainedRun-store shardsEvery service, explainedQueue shardsEvery service, explainedWorkflow runners and step runnersEvery service, explainedConsumer and retained executor WorkersEvery service, explainedIndex shardsEvery service, explainedHook token registriesEvery service, explainedRun streams and VM snapshotsEvery service, explainedR2 payloads and dead lettersEvery service, explainedAlarms and cron recoveryEvery service, explainedState and deliveryHow an event becomes durable work, why the outbox exists, and where transactions stop.The event is the durable recordState and deliveryWhy commit an outbox?State and deliveryHook claims cross transaction boundariesState and deliveryAt-least-once means side effects can repeatState and deliveryRetries, limits and recoveryState and deliveryExecution and replayWorkflow decisions execute inside a deterministic runtime. Step bodies do the I/O outside it. QuickJS and the native engine trade replay work for memory and compatibility.Workflow code is not step codeExecution and replayQuickJS is our defaultExecution and replayThe native engine uses a build-time shimExecution and replayWhat the replay numbers meanExecution and replayShards and placementSpread independent runs, preserve old routing, and keep state near execution where possible. More shards are capacity, not free speed.Time picks the epoch, hash picks the shardShards and placementA location hint is a hintShards and placementWhy creation throughput is highShards and placementMany runs scale better than one enormous runShards and placementPayloads and byte streamsUse values for control data and byte streams for bulk data. Offloading to R2 removes storage-message pressure, not every memory limit.A value still has to fit in memoryPayloads and byte streamsPass a handle, then move bytes incrementallyPayloads and byte streamsThe producer must outlive the step resultPayloads and byte streamsThe current multi-GiB reader problemPayloads and byte streamsCompared with VercelTwo implementations of the same World contract. We can inspect Vercel’s public adapter, not the internals behind its managed APIs.The services Vercel’s public client usesCompared with VercelThe same jobs, different ownersCompared with VercelHow their transport worksCompared with VercelWhere our design helpsCompared with VercelRead the Vercel limits with their runtime contextCompared with VercelMeasurements and limitsRecorded Workers results, the workload behind each number, and the failures that keep these from being unlimited-capacity claims.Latest regression checkMeasurements and limitsCreation is not completionMeasurements and limitsExecution resultsMeasurements and limitsLimits are not all the same kind of numberMeasurements and limitsKnown failure pointsMeasurements and limitsRun the probesMeasurements and limitsIdentity and deploymentsBindings authorize internal access. Your application protects public routes. Encryption and retained release routing solve separate problems.Internal calls use capabilitiesIdentity and deploymentsEncryption has a narrower scope than “all data”Identity and deploymentsKeep the code that owns old historyIdentity and deploymentsHow Vercel’s identity differsIdentity and deploymentsBuild, deploy and operateThe repository root is an example application. The reusable World lives in packages/world-cloudflare. Deploy the minimal mode first, then add retained executors if you need them.Start with the exampleBuild, deploy and operateKnow which config changes affect old runsBuild, deploy and operateDeploy state first, then the retained executorBuild, deploy and operateTest the adapter, the SDK and the deploymentBuild, deploy and operateOperational work still leftBuild, deploy and operate
Local search. Nothing sent to a server.Esc to close
Documentation