DynamicWorkerLoader
Source:
src/Cloudflare/Workers/DynamicWorkerLoader.ts
Load and run ephemeral Workers at runtime from inline JavaScript modules.
DynamicWorkerLoader registers a worker_loader binding on the
parent Worker at deploy time. At runtime you call .load() with
inline module source code and get back a fully typed Worker
instance you can fetch or call RPC methods on. Each loaded
Worker runs in its own isolate with full sandboxing.
This is useful for evaluating user-provided code, running untrusted plugins, or dynamically generating Workers from templates.
Creating a Loader
Section titled “Creating a Loader”Yield Cloudflare.DynamicWorkerLoader(name) in your Worker’s init
phase to register the binding and get back a runtime handle. The
string argument becomes the binding name on the deployed Worker.
Registering a loader (effect-native Worker)
import * as Cloudflare from "alchemy/Cloudflare";import * as Effect from "effect/Effect";import { HttpServerRequest } from "effect/unstable/http/HttpServerRequest";import * as HttpServerResponse from "effect/unstable/http/HttpServerResponse";import * as HttpClientRequest from "effect/unstable/http/HttpClientRequest";
export default class EvalWorker extends Cloudflare.Worker<EvalWorker>()( "EvalWorker", { main: import.meta.filename }, Effect.gen(function* () { // Registers the `worker_loader` binding on this Worker and returns the // runtime handle in one step — no separate `.bind(...)`. const loader = yield* Cloudflare.DynamicWorkerLoader("LOADER");
return { fetch: Effect.gen(function* () { const request = yield* HttpServerRequest; const code = yield* request.text;
// Spin up an isolated, sandboxed Worker from inline source. const worker = loader.load({ compatibilityDate: "2026-01-28", mainModule: "worker.js", modules: { "worker.js": `export default { async fetch(req) { const result = (0, eval)(await req.text()); return new Response(String(result)); } }`, }, globalOutbound: null, // block outbound network access });
// Call the loaded Worker over Effect-native HTTP. const response = yield* worker.fetch( HttpClientRequest.post("https://worker/").pipe( HttpClientRequest.bodyText(code), ), ); return HttpServerResponse.fromClientResponse(response); }), }; }),) {}Declaring on env (async Worker)
export const Worker = Cloudflare.Worker("Worker", { main: "./src/worker.ts", env: { LOADER: Cloudflare.DynamicWorkerLoader() },});
export type WorkerEnv = Cloudflare.InferEnv<typeof Worker>;
// worker.tsexport default { async fetch(req: Request, env: WorkerEnv) { const worker = env.LOADER.load({ compatibilityDate: "2026-01-28", mainModule: "worker.js", modules: { "worker.js": "export default { fetch: () => new Response('ok') }" }, }); return worker.getEntrypoint().fetch(req); },};Loading a Worker
Section titled “Loading a Worker”Call loader.load() with a compatibility date, a main module
name, and a map of module names to source code strings. The
returned instance exposes .fetch() for HTTP and RPC methods
for named entrypoints.
const worker = loader.load({ compatibilityDate: "2026-01-28", mainModule: "worker.js", modules: { "worker.js": `export default { async fetch(request) { return new Response("Hello from dynamic worker!"); } }`, },});
const response = yield* worker.fetch( HttpClientRequest.get("https://worker/"),);Sandboxing
Section titled “Sandboxing”Set globalOutbound to null to block all outbound network
access from the dynamic Worker, or pass an RPC stub to intercept
and proxy outbound requests.
const worker = loader.load({ compatibilityDate: "2026-01-28", mainModule: "worker.js", modules: { "worker.js": `export default { async fetch(req) { // fetch() calls from here will fail return new Response("sandboxed"); } }`, }, globalOutbound: null,});Named Entrypoints
Section titled “Named Entrypoints”If the dynamic Worker exports named entrypoints, use
.getEntrypoint(name) to get a typed stub for calling its
methods.
const worker = loader.load({ ... });const api = worker.getEntrypoint<{ greet: (name: string) => Effect.Effect<string> }>("api");const greeting = yield* api.greet("world");