Skip to content

feat(miniflare,wrangler): cross-worker workflow bindings via dev registry#13863

Merged
petebacondarwin merged 3 commits into
cloudflare:mainfrom
aslakhellesoy:workflow-cross-worker-bindings
Jun 2, 2026
Merged

feat(miniflare,wrangler): cross-worker workflow bindings via dev registry#13863
petebacondarwin merged 3 commits into
cloudflare:mainfrom
aslakhellesoy:workflow-cross-worker-bindings

Conversation

@aslakhellesoy

@aslakhellesoy aslakhellesoy commented May 7, 2026

Copy link
Copy Markdown
Contributor

Workflow bindings get stripped from getPlatformProxy() because miniflare can't run a workflow whose engine lives in another worker. That's fine inside a self-contained wrangler dev, but it kills the split-process model that adapter-cloudflare (SvelteKit, Remix) uses in dev — the user's +server.ts runs in Vite, the workflow class runs in a wrangler sidecar, and platform.env.MY_WORKFLOW.create(...) becomes undefined.create(...).

DOs already work in this setup via script_name cross-worker routing through the dev registry. This PR adds the same for workflows.

  • miniflare: when a workflow's scriptName doesn't refer to a local worker, route the engine's USER_WORKFLOW binding through the existing ExternalServiceProxy on the dev-registry-proxy worker. Same plumbing DOs use; no new proxy class needed because workflows talk to USER_WORKFLOW as a service binding.
  • wrangler: getPlatformProxy() stops stripping workflows that have a script_name (it still strips local ones — the engine has nowhere to go for those).

Tested with a SvelteKit example end-to-end: platform.env.BOT_WORKFLOW.create(...) from a +server.ts now returns a real instance, runs in the sidecar, and a step inside the workflow can call back to a DO and reply over a WebSocket. Unit test added in dev-registry.spec.ts mirrors the existing cross-worker DO tests.

Closes #7459.

  • Tests
    • Tests included/updated
    • Automated tests not possible - manual testing has been completed as follows:
    • Additional testing not necessary because:
  • Public documentation
    • Cloudflare docs PR(s):
    • Documentation not necessary because: only fixes a bug of an existing capability

@changeset-bot

changeset-bot Bot commented May 7, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: c6b104a

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 6 packages
Name Type
wrangler Minor
miniflare Minor
@cloudflare/vite-plugin Patch
@cloudflare/vitest-pool-workers Patch
@cloudflare/wrangler-bundler Patch
@cloudflare/pages-shared Patch

Not sure what this means? Click here to learn what changesets are.

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

@workers-devprod workers-devprod requested review from a team and ascorbic and removed request for a team May 7, 2026 23:15
@workers-devprod

Copy link
Copy Markdown
Contributor

Codeowners approval required for this PR:

  • @cloudflare/wrangler
Show detailed file reviewers
  • .changeset/getplatformproxy-cross-script-workflows.md: [@cloudflare/wrangler]
  • .changeset/workflow-cross-worker-bindings.md: [@cloudflare/wrangler]
  • fixtures/get-platform-proxy/tests/get-platform-proxy.env.test.ts: [@cloudflare/wrangler]
  • packages/miniflare/src/index.ts: [@cloudflare/wrangler]
  • packages/miniflare/src/plugins/workflows/index.ts: [@cloudflare/wrangler]
  • packages/miniflare/test/dev-registry.spec.ts: [@cloudflare/wrangler]
  • packages/wrangler/src/api/integrations/platform/index.ts: [@cloudflare/wrangler]

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 5 additional findings.

Open in Devin Review

@workers-devprod

Copy link
Copy Markdown
Contributor

Codeowners approval required for this PR:

  • @cloudflare/wrangler
Show detailed file reviewers
  • .changeset/getplatformproxy-cross-script-workflows.md: [@cloudflare/wrangler]
  • .changeset/workflow-cross-worker-bindings.md: [@cloudflare/wrangler]
  • fixtures/get-platform-proxy/tests/get-platform-proxy.env.test.ts: [@cloudflare/wrangler]
  • packages/miniflare/src/index.ts: [@cloudflare/wrangler]
  • packages/miniflare/src/plugins/workflows/index.ts: [@cloudflare/wrangler]
  • packages/miniflare/test/dev-registry.spec.ts: [@cloudflare/wrangler]
  • packages/wrangler/src/api/integrations/platform/index.ts: [@cloudflare/wrangler]

@pkg-pr-new

pkg-pr-new Bot commented May 19, 2026

Copy link
Copy Markdown
create-cloudflare

npm i https://pkg.pr.new/create-cloudflare@13863

@cloudflare/deploy-helpers

npm i https://pkg.pr.new/@cloudflare/deploy-helpers@13863

@cloudflare/kv-asset-handler

npm i https://pkg.pr.new/@cloudflare/kv-asset-handler@13863

miniflare

npm i https://pkg.pr.new/miniflare@13863

@cloudflare/pages-shared

npm i https://pkg.pr.new/@cloudflare/pages-shared@13863

@cloudflare/unenv-preset

npm i https://pkg.pr.new/@cloudflare/unenv-preset@13863

@cloudflare/vite-plugin

npm i https://pkg.pr.new/@cloudflare/vite-plugin@13863

@cloudflare/vitest-pool-workers

npm i https://pkg.pr.new/@cloudflare/vitest-pool-workers@13863

@cloudflare/workers-editor-shared

npm i https://pkg.pr.new/@cloudflare/workers-editor-shared@13863

@cloudflare/workers-utils

npm i https://pkg.pr.new/@cloudflare/workers-utils@13863

wrangler

npm i https://pkg.pr.new/wrangler@13863

@cloudflare/wrangler-bundler

npm i https://pkg.pr.new/@cloudflare/wrangler-bundler@13863

commit: c6b104a

aslakhellesoy added a commit to badreddinesaadioui/sveltekit-add-worker-exports that referenced this pull request May 24, 2026
The HTTP-bridge fallback for workflow bindings now lives entirely
under src/bridge/, with the substantive bridge logic in a real
compiled TypeScript file (bridge/dev-handler.ts) instead of a string
template — the cache wrapper now imports `createBridgeFetch` from a
new `./dev-bridge` package subpath, so the only generated TS that
gets written to node_modules/.cache is six lines of glue.

Auto-detection happens in the runtime hook: `if (env[name]) continue`
skips fake-binding injection when a real Workflow stub is present on
`platform.env`. Once miniflare/wrangler ship cross-worker workflow
routing (cloudflare/workers-sdk#13863), real stubs will appear and
the bridge becomes a transparent no-op.

When the upstream PR lands, deleting the bridge is mechanical:
delete src/bridge/, drop the setupBridge call in src/index.ts,
collapse src/hooks.ts to a no-op handle, drop the ./hooks and
./dev-bridge subpath exports. Each affected file has a comment
pointing at the same removal recipe.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
When a workflow binding has a `scriptName` that doesn't match a worker
in the local Miniflare instance, mark it `external` and have the
workflows plugin point the engine's USER_WORKFLOW binding at the
existing dev-registry-proxy worker's `ExternalServiceProxy` entrypoint
(via service `props`). The proxy resolves the target through the
wrangler dev registry and forwards RPC method calls — including
`run()` — to the workflow class running in another Miniflare instance.

This mirrors the cross-worker `scriptName` support that already exists
for Durable Objects (`getExternalServiceEntrypoints` /
`getOutboundDoProxyClassName`); workflows just pass through
`ExternalServiceProxy` rather than needing a per-(scriptName,
className) generated proxy class because their engine talks to
USER_WORKFLOW as a service binding.

Closes cloudflare#7459.
Stop stripping every workflow binding in `getMiniflareOptionsFromConfig`;
strip only those without a `script_name`. Workflows that point at
another worker (`script_name` set) are handed to miniflare unchanged,
which routes the engine binding through the dev-registry-proxy when
the target worker is registered in the wrangler dev registry.

Without `script_name` the workflow's engine still has nowhere to
dispatch USER_WORKFLOW (the proxy worker is empty), so we keep the
existing strip + warn behaviour for that case — just narrow the
warning text to "...without a script_name:".

Pairs with the corresponding miniflare change in this PR.
@petebacondarwin petebacondarwin force-pushed the workflow-cross-worker-bindings branch from 0ee93a5 to 2c4f203 Compare June 2, 2026 08:45
@workers-devprod

workers-devprod commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

Codeowners approval required for this PR:

  • ✅ @cloudflare/wrangler
Show detailed file reviewers

@workers-devprod workers-devprod left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codeowners reviews satisfied

@github-project-automation github-project-automation Bot moved this from Untriaged to Approved in workers-sdk Jun 2, 2026
@petebacondarwin petebacondarwin removed the request for review from ascorbic June 2, 2026 14:30
@petebacondarwin petebacondarwin enabled auto-merge (squash) June 2, 2026 14:30
@petebacondarwin petebacondarwin disabled auto-merge June 2, 2026 15:08
@petebacondarwin petebacondarwin merged commit 3b8b80a into cloudflare:main Jun 2, 2026
66 of 69 checks passed
@github-project-automation github-project-automation Bot moved this from Approved to Done in workers-sdk Jun 2, 2026
aslakhellesoy added a commit to oselvar/sveltekit-add-worker-exports that referenced this pull request Jun 4, 2026
wrangler 4.98.0 (cloudflare/workers-sdk#13863) fixes cross-worker
workflow routing in getPlatformProxy, so workflow bindings now reach
the sidecar via script_name like Durable Objects do. The HTTP bridge
fallback, service binding, and runtime hook that synthesised
Workflow-shaped objects on platform.env are no longer needed:

- Delete src/bridge/ (dev-handler, runtime-hook, setup) and the
  ./dev-bridge package export.
- Point the dev config's main directly at options.entryPoint instead
  of the generated cache wrapper.
- Reduce src/hooks.ts to a no-op passthrough (kept for backwards
  compatibility with users already wiring it into hooks.server.ts).
- Update README to drop the bridge wiring section and example to drop
  hooks.server.ts.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
aslakhellesoy added a commit to oselvar/sveltekit-add-worker-exports that referenced this pull request Jun 6, 2026
The `/hooks` subpath exported a no-op `Handle` kept for backwards
compatibility after wrangler 4.98.0 fixed cross-worker workflow routing
in getPlatformProxy (cloudflare/workers-sdk#13863). No longer needed.

BREAKING CHANGE: `import { handle } from '@oselvar/sveltekit-add-worker-exports/hooks'`
no longer resolves. Remove the import from your `src/hooks.server.ts`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

🚀 Feature Request: Add support for cross script workflow bindings for getPlatformProxy

3 participants