diff --git a/docs/content/docs/deploying/world/cloudflare-world.mdx b/docs/content/docs/deploying/world/cloudflare-world.mdx
new file mode 100644
index 0000000000..a8f9c31957
--- /dev/null
+++ b/docs/content/docs/deploying/world/cloudflare-world.mdx
@@ -0,0 +1,121 @@
+---
+title: Cloudflare Workers World
+description: Community world using Durable Objects, D1, and Cloudflare Queues.
+type: integration
+summary: Deploy workflows to Cloudflare Workers using Durable Objects for state, D1 for indexing, and Queues for dispatch.
+prerequisites:
+ - /docs/deploying
+related:
+ - /docs/deploying/world/local-world
+ - /docs/deploying/world/vercel-world
+ - /docs/deploying/world/postgres-world
+---
+
+The Cloudflare Workers World is a community-maintained backend that runs workflows on [Cloudflare's edge network](https://workers.cloudflare.com). It uses three Cloudflare primitives for a fully serverless architecture:
+
+- **Durable Objects** for per-run state (events, steps, hooks, waits, streams)
+- **D1 (SQLite)** for cross-run index queries
+- **Cloudflare Queues** for reliable message dispatch
+
+
+This is a community World maintained at [`@ataylorme/workflow-world-cloudflare`](https://github.com/ataylorme/workflow-world-cloudflare). For issues and contributions, visit the [GitHub repository](https://github.com/ataylorme/workflow-world-cloudflare).
+
+
+## Installation
+
+Install the package:
+
+```package-install
+@ataylorme/workflow-world-cloudflare
+```
+
+## Cloudflare Bindings
+
+Configure your `wrangler.toml` with the required bindings:
+
+```toml title="wrangler.toml"
+name = "my-workflow-worker"
+main = "src/worker.ts"
+compatibility_date = "2024-12-01"
+
+[durable_objects]
+bindings = [
+ { name = "WORKFLOW_RUNS", class_name = "WorkflowRunDO" }
+]
+
+[[d1_databases]]
+binding = "WORKFLOW_DB"
+database_name = "workflow"
+database_id = ""
+
+[[queues.producers]]
+binding = "WORKFLOW_QUEUE"
+queue = "workflow-jobs"
+
+[[queues.consumers]]
+queue = "workflow-jobs"
+max_batch_size = 10
+max_retries = 3
+
+[[migrations]]
+tag = "v1"
+new_classes = ["WorkflowRunDO"]
+```
+
+## Database Migration
+
+Run the D1 migration to create index tables. This is idempotent and safe to run multiple times:
+
+```ts
+import { migrate } from '@ataylorme/workflow-world-cloudflare/d1';
+
+await migrate(env.WORKFLOW_DB);
+```
+
+## Usage
+
+Create the world in your Worker and re-export the Durable Object class:
+
+```ts title="src/worker.ts" lineNumbers
+import { createWorld, WorkflowRunDO } from '@ataylorme/workflow-world-cloudflare';
+
+// Re-export the DO class so Cloudflare can instantiate it
+export { WorkflowRunDO };
+
+export default {
+ async fetch(request, env) {
+ const world = createWorld({
+ db: env.WORKFLOW_DB,
+ runs: env.WORKFLOW_RUNS,
+ queue: env.WORKFLOW_QUEUE,
+ });
+ // Use world with your workflow runtime...
+ },
+
+ async queue(batch, env) {
+ const world = createWorld({
+ db: env.WORKFLOW_DB,
+ runs: env.WORKFLOW_RUNS,
+ queue: env.WORKFLOW_QUEUE,
+ });
+ await world.handleQueueBatch(batch);
+ },
+};
+```
+
+## How It Works
+
+Each workflow run maps 1:1 to a Durable Object instance. All per-run state lives in the DO's transactional storage, which provides strong consistency without external databases.
+
+D1 maintains a lightweight global index so that cross-run queries (`runs.list`, `hooks.getByToken`) work without needing to fan out to every DO. The DO writes index updates to D1 fire-and-forget after each mutation.
+
+Workflow and step invocations are dispatched through Cloudflare Queues for reliable, at-least-once delivery.
+
+## Limitations
+
+- **`events.listByCorrelationId()`** — Requires `runId` context; the DO-per-run architecture cannot query across runs without knowing which DO to target
+- **`steps.get()`** — Requires `runId` for the same routing reason
+- **`readFromStream()`** — Expects stream names in `runId:streamName` format because the Streamer interface does not pass `runId` for reads
+- **Cloudflare platform** — Requires Cloudflare Workers with Durable Objects, D1, and Queues enabled
+
+For local development, use the [Local World](/worlds/local) which requires no external services.
diff --git a/docs/content/docs/deploying/world/meta.json b/docs/content/docs/deploying/world/meta.json
index 0cb3e7c432..1cb96c4c74 100644
--- a/docs/content/docs/deploying/world/meta.json
+++ b/docs/content/docs/deploying/world/meta.json
@@ -1,4 +1,4 @@
{
"title": "World",
- "pages": ["local-world", "vercel-world", "postgres-world"]
+ "pages": ["local-world", "vercel-world", "postgres-world", "cloudflare-world"]
}
diff --git a/worlds-manifest.json b/worlds-manifest.json
index 4e72dc0174..ffccf06aff 100644
--- a/worlds-manifest.json
+++ b/worlds-manifest.json
@@ -144,6 +144,20 @@
"services": [],
"requiresCredentials": true,
"credentialsNote": "Requires JAZZ_API_KEY, JAZZ_WORKER_ACCOUNT, and JAZZ_WORKER_SECRET from Jazz Cloud"
+ },
+ {
+ "id": "cloudflare",
+ "type": "community",
+ "package": "@ataylorme/workflow-world-cloudflare",
+ "name": "Cloudflare Workers",
+ "description": "Cloudflare Workers world using Durable Objects for per-run state, D1 for cross-run queries, and Cloudflare Queues for message dispatch",
+ "repository": "https://github.com/ataylorme/workflow-world-cloudflare",
+ "docs": "/docs/deploying/world/cloudflare-world",
+ "features": [],
+ "env": {
+ "WORKFLOW_TARGET_WORLD": "@ataylorme/workflow-world-cloudflare"
+ },
+ "services": []
}
]
}