Skip to content

Evaluate adopting dynamic-worker engine for host-cloudflare (Worker Loaders now open beta) #12

Description

@amondnet

Summary

Cloudflare Worker Loaders (Dynamic Workers) moved to open beta on
2026-03-24
, available to all paid Workers users. apps/host-cloudflare
currently runs the interim QuickJS-WASM substrate specifically because Worker
Loaders was in closed beta. That constraint is now lifted, so we can evaluate
switching host-cloudflare's engine seam from QuickJS to the
dynamic-worker executor (the same one apps/cloud uses), and the stale
"closed beta" comments/docs should be updated regardless.

Background

The code documents QuickJS as a temporary accommodation, not a preference:

// apps/host-cloudflare/src/execution.ts:21-26
// QuickJS-wasm is the default code substrate because it runs in a single Worker
// with no extra binding. When Cloudflare's dynamic Worker Loader leaves closed
// beta, swap CodeExecutorProvider for the dynamic-worker executor (cloud's) —
// it's a one-Layer change behind this same seam.

host-cloudflare/README.md:87-89 and notes/research/product-model.md:89
echo the same: dynamic-worker is the intended cloud runtime.

Latest status (now open beta):

What switching would gain (capability, not just speed)

QuickJS has hard limitations the dynamic-worker runtime does not:

  • Binary values: QuickJS cannot represent Blob/File/Uint8Array at the
    tool boundary at all; dynamic-worker passes them via structured clone + a
    tagged-ArrayBuffer codec.
  • Serialization fidelity: QuickJS forces JSON round-trips, losing Date /
    Map / Set; dynamic-worker uses Workers RPC structured clone.
  • Node APIs / network: QuickJS blocks fetch and has no nodejs_compat
    inside the WASM context; dynamic-worker has nodejs_compat and configurable
    globalOutbound.
  • Isolation: separate workerd isolate vs WASM memory space inside the same
    isolate.

Performance is workload-dependent and unmeasured in this repo (the "100x"
figure is isolates-vs-containers, not vs QuickJS). Isolate boot is a few ms, and
warm-cache reuse via get(id) can remove most of the per-call cost (tracked
separately as the warm-cache key fix).

Scope

  • Swap CloudflareCodeExecutorProvider in
    apps/host-cloudflare/src/execution.ts from makeQuickJsExecutor() to
    makeDynamicWorkerExecutor({ loader: env.LOADER }) behind the existing
    CodeExecutor seam (the "one-Layer change" the comment describes).
  • Add the worker_loaders binding (LOADER) to
    apps/host-cloudflare/wrangler.jsonc.
  • Confirm the deployment's Workers plan is paid (open-beta requirement).
  • Decide whether QuickJS stays as a fallback or is removed for host-cloudflare.
  • Update the stale "closed beta" comments and README.md seam table
    (the README already lags reality on R2 blobs + the MCP-session Durable
    Object — refresh those while here).
  • e2e coverage proving code execution + binary/tool I/O works on the new
    runtime; gate with format:check / lint / typecheck / test.

Relationship to other work

  • Depends on / benefits from the warm-cache get(id) key fix in
    runtime-dynamic-worker (separate issue) for latency.
  • Independent of the github_app auth work (separate issue).

Decision needed

Whether to actually adopt dynamic-worker for host-cloudflare now, or only
update the stale docs/comments and keep QuickJS until a benchmark justifies the
switch. This issue tracks the evaluation; the doc/comment refresh is worth doing
either way.


Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions