Skip to main content
Comparison

Secure Exec vs Cloudflare Workers

How Secure Exec and Cloudflare Workers differ for running generated or user-written code: form factor, limits, Node.js compatibility, and cost.

Both run untrusted JavaScript on V8, but they solve different problems. Workers is a managed edge platform: you send code to Cloudflare and Cloudflare runs it. That includes Dynamic Workers, its API for loading generated code at runtime. Secure Exec is a library you embed in your own backend, so the code and its data never leave your infrastructure.

Cloudflare’s Sandbox SDK is a separate, container-based product. See Secure Exec vs Container Sandboxes.

At a glance

Secure ExecCloudflare Workers
Form factorA library. Runs where your app runsA managed platform. Code and data go to Cloudflare
Cost to startNoneDynamic Workers need the Workers Paid plan
Memory per guestConfigurable128 MB
Node.js APIsnode:fs, node:net, node:child_process against a virtual kernelA subset. Many modules are non-functional stubs
FilesystemVirtual filesystem, persistent in a VMAn in-memory /tmp, unique to each request
Subprocesses and serversYesNo
npm at runtimeInstall or mount packagesBundle before you load the code
TypeScriptRuns, and type-checks with the real compilerCompile it yourself first
Outbound networkDenied by defaultAllowed by default
State between callsVMs and contextsNone without Durable Objects

Where Workers falls short

  • It is someone else’s computer. Generated code and the data it touches leave your infrastructure, and every call needs a Cloudflare account. You cannot run it safely on your own machines either: the open source runtime’s README warns that “workerd is not a hardened sandbox… you must run it inside an appropriate secure sandbox, such as a virtual machine.”
  • Dynamic Workers cost money from the first call. They “are currently only available on the Workers Paid plan”, which has a “minimum charge of $5 USD per month”, and are billed at “$0.002 per Dynamic Worker per day”. Without an ID, each invocation counts as a new Dynamic Worker.
  • The network is open unless you close it. “If globalOutbound is not specified, the default is to inherit the parent’s network access, which usually means the dynamic Worker will have full access to the public Internet.” An allowlist means writing your own gateway.
  • Node.js support is a subset. The docs list node:child_process, worker_threads, vm, cluster, dgram, http2, readline, tty, and others as “non-functional stub modules”. node:net cannot listen: “net.Server class is not supported”.
  • The filesystem does not persist. The “contents of /tmp are not persistent and are unique to each request”, file permissions “are not supported”, and files count against the 128 MB memory limit.
  • There is no build step and no type-checking. “Languages like TypeScript must be compiled to JavaScript before being passed to load()”, and dependencies “must be transpiled and bundled” first. eval() and new Function are not allowed.
  • Limits are fixed by the platform. Memory is 128 MB per isolate, including WebAssembly. Per-call limits cover CPU time and subrequests only. A Worker request can have in-flight requests to at most four distinct Dynamic Workers.
  • The clock does not move during computation. “performance.now() and Date.now(), only advance or increment after I/O occurs”, so guest code cannot time its own work.
  • Logs disappear by default. Dynamic Worker logs “are discarded after the Dynamic Worker finishes” unless you build log capture with a Tail Worker.
  • State does not survive. “It is never guaranteed that two requests will go to the same isolate.”

What Workers does well

Isolates start in a few milliseconds and run in hundreds of locations, with nothing for you to operate. Cloudflare’s multi-tenant isolation is proven at enormous scale and layered with process-level sandboxing and fast V8 patching. Its capability bindings are well designed: they are plain JavaScript objects that cannot be forged.

Only choose Cloudflare Workers when

All of these hold:

  1. You already build on Cloudflare, and sending generated code and its data to a third-party platform is acceptable.
  2. The code is short, stateless JavaScript that only calls capabilities you hand it. It needs no subprocesses, servers, persistent files, or runtime installs, and fits in 128 MB.
  3. You will do the bundling, type-checking, egress allowlisting, and log capture yourself.
  4. Edge latency and zero operations matter more to you than Node.js fidelity or keeping execution inside your own infrastructure.

Choose Secure Exec when

You need to run someone else’s code from inside your own backend, with real Node.js semantics, per-call permissions that deny the network by default, and no vendor in the path.