Start here
The architecture
An ordered store for each run, delivery capacity shared across shards, and execution kept off the queue objects.
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 resource | What lives there |
|---|---|
| Main Worker | Example HTTP routes, World adapter, queue consumer and Durable Object class exports. The dispatcher entry point excludes the workflow bundle. |
| WORLD_STORE namespace | Run stores, token registries and listing indexes, all backed by WorldStore objects with distinct names. |
| QUEUE_SHARD namespace | Durable queue shards implemented with SQLite and durability. This is not the Cloudflare Queues product. |
| RUNNER namespace | Shared workflow runners and step runners. A run deterministically reaches its workflow runner. |
| RUN_STREAMS namespace | An object per run for stream metadata, chunk references and VM snapshot parts. |
| R2 buckets | PAYLOADS for large values and chunks; DLQ for exhausted queue messages. |
| Optional WFP namespace | Release-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.
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
| Choice | Benefit | Cost |
|---|---|---|
| Warm shared stores | Avoid a fresh named store object for every creation. | Runs share a store’s CPU and memory budget. |
| Separate delivery lanes | An open replay delivery does not consume the step lane. | More delivery and recovery logic to maintain. |
| Outbox-fed indexes | Creation need not wait for every list index. | Lists are eventually consistent; backfill can be expensive. |
| Retained executors | Old runs can target the code they started with. | You must retain scripts, routes and compatible RPC methods. |
| QuickJS snapshots | Skip much of the earlier replay work. | Snapshot compatibility, memory and SDK coupling matter. |
Sources and implementation
- packages/world-cloudflare/src/lib/shards.ts
- packages/world-cloudflare/src/store/world-store.ts
- packages/world-cloudflare/src/queue/consumer.ts
Repository links may require access. Vercel links point to public source or published documentation. Logical API names do not establish backend internals.