Skip to content

Simplify Cloudflare Durable Object framework integration - #7385

Open
IMax153 wants to merge 3 commits into
eff-698-cloudflare-clusterfrom
cloudflare-durable-object-programs
Open

Simplify Cloudflare Durable Object framework integration#7385
IMax153 wants to merge 3 commits into
eff-698-cloudflare-clusterfrom
cloudflare-durable-object-programs

Conversation

@IMax153

@IMax153 IMax153 commented Aug 21, 2026

Copy link
Copy Markdown
Member

Motivation

Frameworks such as Alchemy can generate the native Durable Object class, but the existing integration requires consumers to reconstruct internal lifecycle details: manually retain an unsafe scope, register workflows inside the object isolate, branch on optional program readiness, forward every RPC method, and read the workflow namespace from an untyped Worker environment. Those steps are easy to attach to the wrong lifetime and make the class-independent API harder to use safely.

This change makes the Durable Object lifecycle explicit while keeping Effect Workflow, Cluster, and the Cloudflare runtime independent of any deployment framework.

Changes

  • Add class-independent initialization Effects for entity, workflow, durable queue, and singleton Durable Objects.
  • Restore persisted alarms before returning each Effect-valued handler object, eliminating separate program.ready handling.
  • Delegate the bundled native classes to the same programs through blockConcurrencyWhile.
  • Let the workflow engine consume the namespace getByName capability and both Promise- and Effect-valued workflow RPC methods.
  • Export the program module publicly.
  • Add focused coverage for initialization, alarm restoration, alarm-wake name recovery, and Effect-valued RPC clients.

Alchemy integration

Alchemy can yield its generated Durable Object namespace directly and construct ordinary Layers during Worker initialization:

const workflowNamespace = yield* ClusterWorkflow
const MainLayer = GreetingWorkflowLayer.pipe(
  Layer.provideMerge(CloudflareWorkflowEngine.layer({ workflowNamespace }))
)
const context = yield* Layer.build(MainLayer)

The generated Durable Object definition only obtains its platform state and returns makeClusterWorkflowProgram(state.raw). It does not need WorkerEnvironment, Scope.makeUnsafe(), a readiness branch, registry knowledge, or method-by-method forwarding. Alchemy remains responsible only for deployment and native class generation.

Lifecycle

Workflow registration is built in the Worker initialization scope, which Alchemy retains for the isolate lifetime. Durable Object reconstruction remains storage-driven, alarms recover execution identity from SQLite, and detached work continues through native waitUntil. Native classes preserve their existing behavior while sharing the framework-neutral implementation.

Validation

  • nix develop --command pnpm lint-fix
  • nix develop --command pnpm --filter @effect/platform-cloudflare check
  • Targeted CloudflareWorkflowEngine.test.ts
  • Targeted CloudflareDurableObjects.test.ts
  • Local Alchemy workflow start, durable sleep, completion, and restart persistence smoke check

@changeset-bot

changeset-bot Bot commented Aug 21, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 054dea3

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes changesets to release 31 packages
Name Type
effect Patch
@effect/ai-anthropic Patch
@effect/ai-openai Patch
@effect/ai-openai-compat Patch
@effect/ai-openrouter Patch
@effect/atom-react Patch
@effect/atom-solid Patch
@effect/atom-vue Patch
@effect/docgen Patch
@effect/doctest Patch
@effect/openapi-generator Patch
@effect/opentelemetry Patch
@effect/platform-browser Patch
@effect/platform-bun Patch
@effect/platform-cloudflare Patch
@effect/platform-deno Patch
@effect/platform-node Patch
@effect/platform-node-shared Patch
@effect/sql-clickhouse Patch
@effect/sql-d1 Patch
@effect/sql-libsql Patch
@effect/sql-mssql Patch
@effect/sql-mysql2 Patch
@effect/sql-pg Patch
@effect/sql-pglite Patch
@effect/sql-sqlite-bun Patch
@effect/sql-sqlite-do Patch
@effect/sql-sqlite-node Patch
@effect/sql-sqlite-react-native Patch
@effect/sql-sqlite-wasm Patch
@effect/vitest Patch

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@effect-slopcop effect-slopcop Bot added the bug Something isn't working label Aug 21, 2026
@effect-slopcop effect-slopcop Bot added enhancement New feature or request and removed bug Something isn't working labels Aug 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant