World / Cloudflare
GitHub

Start here

Life of a request

Follow the ordinary static-workflow start path, then the deliveries that turn the stored intent into completed work.

Both implementations run the same core SDK. The main difference is what answers core’s storage and queue calls. This walkthrough separates accepting a run from finishing it.

Our World: accepting the run

  1. App → SDK

    The route calls start()

    The example validates the request and resolves a generated workflow ID. Direct SDK callers can skip the HTTP layer. Core resolves the World, target deployment and capabilities, then mints the run ID.

  2. SDK in the calling Worker

    Prepare arguments and execution policy

    Core records the engine and execution context. If encryption is enabled, it obtains key material and encrypts serialized values. Cross-deployment starts may probe the target first.

  3. SDK → store and dispatch

    Persist creation and publish concurrently

    Core launches the creation event and start publication in parallel. Publication passes through the store’s dispatch code; these are not simply two isolated RPC calls. The start message carries enough creation data for recovery.

  4. Store → R2 / SQLite → queue shard

    Commit state and durable intent

    Large payloads reach R2 before the referencing event. The store commits event, materialized state and outbox debt in a transaction. Dispatch first touches the shared workflow runner from the store, then hands the message to a queue shard.

  5. SDK → app → caller

    Return a handle, not the result

    The example returns 202 and a run ID. Core examines both start outcomes. A retryable creation failure after successful queue admission can be recovered by the consumer. Conversely, a thrown start error does not prove nothing was persisted.

Our World: delivering and running

  1. Queue alarm → workflow runner

    Start a durable delivery

    The queue claims work on its replay lane. Run deliveries serialize per run, not across all runs on the shard. Alarm-created runner stubs prevent enqueue/replay cycles from continually extending the original subrequest chain.

  2. Runner → consumer → executor

    Select the release

    The consumer maps the recorded deployment ID through EXECUTOR_ROUTES and calls its script in the dispatch namespace. Without WFP, it executes locally. A fresh request and SDK route do not imply a fresh Workers isolate.

  3. SDK ↔ store / run streams

    Reconstruct the workflow

    Core records or reconstructs the running state, reads event pages and restores a usable QuickJS snapshot if present. Workflow decisions run inside the VM. External I/O belongs in step functions outside that VM.

  4. Executor → steps / queue shards

    Execute inline or dispatch

    Some steps run inline. Other steps are queued by key across shards and handled through step runners. Concurrent step creations and publishes gather into request-scoped batches, capped at 500 items and two calls in flight.

  5. Step → store → replay lane

    Record the result and continue

    The step writes started and completed or failed events. A continuation wakes the run. Eligible pure wakes coalesce behind a successful replay, reducing redundant work without discarding distinct inputs.

  6. SDK → store → indexes

    Suspend or finish

    A hook or sleep persists a waiting condition rather than holding an HTTP request open. On completion, the output and terminal state persist. Index pushes make the final state visible to cross-run listings, subject to eventual consistency.

Vercel: the corresponding path

  1. App Function → SDK

    Resolve deployment, region and encryption

    The adapter supplies deployment identity and a region-tagged run ID. Core serializes the arguments and prepares encryption. Deployment resolution and cross-deployment probes happen when needed.

  2. Function → Workflow API + Vercel Queues

    Store creation and send the start

    Core concurrently sends run_created to the managed Workflow API and publishes to the workflow’s regional topic. Queue options identify the target deployment. The same resilient-start rules apply.

  3. Vercel Queues → flow Function

    Deliver the message

    The queue handler retrieves and leases a platform-delivered message. The combined SDK route handles workflow and queued-step messages; not every step requires its own Function invocation.

  4. Core ↔ managed Workflow API

    Execute and record

    The default engine is native Node. QuickJS is available as an opt-in. Event writes can use a per-run WebSocket channel; batch writes and listings remain HTTP. Events use binary frames with CBOR metadata and opaque payload bytes.

  5. Core → queue → Function

    Continue until completion

    Core queues continuations as needed and uses recorded step outcomes on replay. Spec 9 adds a per-run concurrency key. Streams and snapshots go through the managed API, whose backend internals are not established by the public client source.

What a response does and does not guarantee

ObservationMeaning
202 from the exampleThe start path returned a handle. It does not mean workflow steps completed.
Step completed eventThe result is durable. An external side effect before that event may have happened more than once.
Retryable 503An infrastructure operation failed transiently. Use an application-level idempotency strategy when retrying starts; do not blindly assume the first attempt created nothing.
Listed as runningA projected list row can lag the run’s authoritative state.

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