This site is not affiliated with or endorsed by Cloudflare, Inc. It showcases deployable experiments across most Cloudflare products.
Compute & Isolation

Dynamic Worker Runner

Execute untrusted JavaScript via Dynamic Workers with no network access - isolate and run user code safely

Run untrusted JavaScript as an ES module Worker using the Worker Loader API. Loaded workers run with globalOutbound: null so they cannot make network requests.

API Reference

POST /run

Execute a Worker module string and return its HTTP response status and body.

code string (required)

Full ES module that exports default { fetch }. Max length 10,000 characters.

Example Request

curl -X POST "https://your-worker.workers.dev/run" \
  -H "Content-Type: application/json" \
  -d '{"code":"export default { async fetch() { return Response.json({ hello: \"world\" }); } }"}'

Success Response

{
  "status": 200,
  "body": { "hello": "world" }
}

Error Codes

  • 400 - Missing, empty, or too-long code (INVALID_CODE)
  • 502 - Loader or isolate failure (RUN_ERROR)

Use Cases

  • Learn Dynamic Workers / Worker Loader patterns safely
  • Sandbox plugin or customer code without outbound network
  • Prototype multi-tenant execution before Workers for Platforms
  • Teach isolate isolation and globalOutbound restrictions

Limitations

  • Code must be a complete ES module with default { fetch }
  • Max code length 10,000 characters
  • No outbound network from the loaded worker
  • Dynamic Workers / Worker Loader may require account entitlements

Use in your project

Copy these files into an existing Worker. Prefer Deployment to try the full experiment first. Source: apps/experiments/dynamic-worker-runner.

DependenciesNoneBindingsNonePlatformWeb Crypto, Fetch API
import { COMPATIBILITY_DATE, MAIN_MODULE, MAX_CODE_LENGTH } from "../constants/defaults";import type { Env, WorkerCode } from "../types/env";import type { RunResult } from "../types/run";export function validateCode(input: string | undefined): string | null {  if (typeof input !== "string") return null;  const trimmed = input.trim();  if (!trimmed || trimmed.length > MAX_CODE_LENGTH) return null;  return trimmed;}export function buildWorkerCode(code: string): WorkerCode {  return {    compatibilityDate: COMPATIBILITY_DATE,    mainModule: MAIN_MODULE,    modules: {      [MAIN_MODULE]: code,    },    globalOutbound: null,  };}async function hashId(code: string): Promise<string> {  const data = new TextEncoder().encode(code);  const digest = await crypto.subtle.digest("SHA-256", data);  return Array.from(new Uint8Array(digest))    .map((b) => b.toString(16).padStart(2, "0"))    .join("")    .slice(0, 32);}export async function runDynamicWorker(env: Env, code: string): Promise<RunResult> {  if (!env.LOADER) {    throw new Error("LOADER binding is not configured");  }  const id = await hashId(code);  const workerCode = buildWorkerCode(code);  const stub = env.LOADER.get(id, () => workerCode);  const entrypoint = stub.getEntrypoint();  const response = await entrypoint.fetch(new Request("https://dynamic-worker/"));  const contentType = response.headers.get("content-type") ?? "";  let body: unknown;  if (contentType.includes("application/json")) {    body = await response.json();  } else {    body = await response.text();  }  return { status: response.status, body };}

Deployment

Click the deploy button

Deploy to Cloudflare Workers

Deploy

Ensure your account supports Worker Loaders. wrangler.json binds LOADER via worker_loaders.

Test your deployment

curl -X POST "https://your-worker.workers.dev/run" \
  -H "Content-Type: application/json" \
  -d '{"code":"export default { async fetch() { return Response.json({ ok: true }); } }"}'

Local Development

cd apps/experiments/dynamic-worker-runner
npm install
npm run dev
curl -X POST "http://localhost:8787/run" \
  -H "Content-Type: application/json" \
  -d '{"code":"export default { async fetch() { return Response.json({ hello: \"world\" }); } }"}'

Configuration

wrangler.json declares:

  • Worker Loader binding LOADER

Cloudflare Features Used

On this page