Skip to content

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.

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.ts
export 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);
},
};

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/"),
);

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,
});

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");