|
| 1 | +--- |
| 2 | +title: Cloudflare Workers Comparison |
| 3 | +description: Node.js API compatibility comparison between secure-exec and Cloudflare Workers (standard, Workers for Platforms, dynamic dispatch). |
| 4 | +--- |
| 5 | + |
| 6 | +*Last updated: 2026-03-10* |
| 7 | + |
| 8 | +## Overview |
| 9 | + |
| 10 | +This document compares Node.js API support across **secure-exec** and three Cloudflare Workers deployment models: |
| 11 | + |
| 12 | +| Platform | Description | |
| 13 | +| --- | --- | |
| 14 | +| **CF Workers** | Standard Cloudflare Workers with `nodejs_compat` flag and compatibility date ≥ 2024-09-23. | |
| 15 | +| **CF Workers for Platforms** | Multi-tenant variant where platform operators deploy user Workers into dispatch namespaces. Same V8 runtime as standard Workers; additional isolation constraints. | |
| 16 | +| **CF Dynamic Dispatch** | The routing Worker that invokes user Workers in a Workers for Platforms namespace. Runs as a standard Worker with dispatch namespace bindings. | |
| 17 | + |
| 18 | +All three CF deployment models share the same `nodejs_compat` API surface. WfP adds operational restrictions (no `caches.default`, no `request.cf` without trusted mode, no gradual deployments, operator-enforced CPU/subrequest limits, outbound Worker interception) but no Node.js API differences. |
| 19 | + |
| 20 | +--- |
| 21 | + |
| 22 | +## Support Tier Legend |
| 23 | + |
| 24 | +| Icon | Meaning | |
| 25 | +| --- | --- | |
| 26 | +| 🟢 | Supported — native or full implementation. | |
| 27 | +| 🔵 | Planned — not yet implemented; on the roadmap. | |
| 28 | +| 🟡 | Partial — functional with behavioral gaps or wrapper limitations. | |
| 29 | +| ⚪ | TBD — under consideration; not yet committed. | |
| 30 | +| 🔴 | Stub — requireable but most APIs throw on call. | |
| 31 | +| ⛔ | Unsupported — not available; `require()` throws immediately. | |
| 32 | + |
| 33 | +--- |
| 34 | + |
| 35 | +## Module Compatibility Matrix |
| 36 | + |
| 37 | +### Core I/O and Networking |
| 38 | + |
| 39 | +| Module | secure-exec | CF Workers (`nodejs_compat`) | Notes | |
| 40 | +| --- | --- | --- | --- | |
| 41 | +| **`fs`** | 🟡 Core I/O: `readFile`, `writeFile`, `appendFile`, `open`, `read`, `write`, `close`, `readdir`, `mkdir`, `rmdir`, `rm`, `unlink`, `stat`, `lstat`, `rename`, `copyFile`, `exists`, `createReadStream`, `createWriteStream`, `writev`, `access`, `realpath`. Missing: `cp`, `glob`, `opendir`, `mkdtemp`, `statfs`, `readv`, `fdatasync`, `fsync`. Deferred: `watch`, `watchFile`, `chmod`, `chown`, `link`, `symlink`, `readlink`, `truncate`, `utimes`. Full coverage planned. | 🟡 In-memory VFS only. `/bundle` (read-only), `/tmp` (writable, ephemeral per-request), `/dev` devices. Missing: `watch`, `watchFile`, `globSync`, file permissions/ownership. All operations synchronous regardless of API style. Timestamps frozen to Unix epoch. 128 MB max file size. | **secure-exec**: Permission-gated; filesystem behavior determined by system driver (host FS or VFS). Read-only `/app/node_modules` overlay. **CF**: No persistent storage; `/tmp` contents isolated per request and lost after response; no real permissions or ownership. | |
| 42 | +| **`http`** | 🟡 `request`, `get`, `createServer` with bridged request/response classes. Fetch-based, fully buffered. No connection pooling, no keep-alive tuning, no WebSocket upgrade, no trailer headers. `Agent` is stub-only. | 🟡 `request`, `get`, `createServer` via fetch API wrapper. Requires extra compat flags. No `Connection` headers, no `Expect: 100-continue`, no socket-level events (`socket`, `upgrade`), no 1xx responses, no trailer headers. `Agent` is stub-only. | | |
| 43 | +| **`https`** | 🟡 Same contract and limitations as `http`. | 🟡 Same wrapper model and limitations as `http`. | | |
| 44 | +| **`http2`** | 🔴 Compatibility classes only; `createServer`/`createSecureServer` throw. | 🔴 Non-functional stub. | Neither platform supports HTTP/2 server creation. | |
| 45 | +| **`net`** | 🔵 Planned. | 🟡 `net.connect()` / `net.Socket` for outbound TCP via Cloudflare Sockets API. No `net.createServer()`. | **CF**: Outbound TCP connections supported. **secure-exec**: On roadmap. | |
| 46 | +| **`tls`** | 🔵 Planned. | 🟡 `tls.connect()` for outbound TLS via Sockets API. No `tls.createServer()`. | **CF**: Outbound TLS supported. **secure-exec**: On roadmap. | |
| 47 | +| **`dns`** | 🟢 `lookup`, `resolve`, `resolve4`, `resolve6`, plus `dns.promises`. | 🟡 DNS over HTTPS via Cloudflare 1.1.1.1. `lookup`, `lookupService`, `resolve` (generic) throw "Not implemented". | **secure-exec**: Permission-gated real DNS. **CF**: DoH only; core methods missing. | |
| 48 | +| **`dgram`** | ⛔ `require()` throws. | 🔴 Non-functional stub. | Neither platform supports UDP sockets. | |
| 49 | + |
| 50 | +### Process and Runtime |
| 51 | + |
| 52 | +| Module | secure-exec | CF Workers (`nodejs_compat`) | Notes | |
| 53 | +| --- | --- | --- | --- | |
| 54 | +| **`process`** | 🟢 `env` (permission-gated), `cwd`/`chdir`, `exit`, timers, stdio event emitters, `hrtime`, `platform`, `arch`, `version`, `argv`, `pid`, `ppid`, `uid`, `gid`. | 🟡 `env`, `cwd`/`chdir`, `exit`, `nextTick`, `stdin`/`stdout`/`stderr`, `platform`, `arch`, `version`. No real process IDs or OS-level user/group IDs. Requires extra `enable_nodejs_process_v2` flag for full surface. | **secure-exec**: Configurable timing mitigation (`freeze` mode); real `pid`/`uid`/`gid` metadata. **CF**: Synthetic process metadata. | |
| 55 | +| **`child_process`** | 🟢 `spawn`, `spawnSync`, `exec`, `execSync`, `execFile`, `execFileSync`. `fork` unsupported. | 🔴 Non-functional stub; all methods throw. | **secure-exec**: Bound to the system driver; subprocess behavior determined by driver implementation. CF has no subprocess support. | |
| 56 | +| **`os`** | 🟢 `platform`, `arch`, `type`, `release`, `version`, `homedir`, `tmpdir`, `hostname`, `userInfo`, `os.constants`. | 🟡 Basic platform/arch metadata. | **secure-exec**: Richer OS metadata surface. | |
| 57 | +| **`worker_threads`** | ⛔ Stubs that throw on API call. | 🔴 Non-functional stub. | Neither platform supports worker threads. | |
| 58 | +| **`cluster`** | ⛔ `require()` throws. | 🔴 Non-functional stub. | Neither platform supports clustering. | |
| 59 | +| **`timers`** | 🟢 `setTimeout`, `clearTimeout`, `setInterval`, `clearInterval`, `setImmediate`, `clearImmediate`. | 🟢 Same surface; returns `Timeout` objects. | Equivalent support. | |
| 60 | +| **`vm`** | 🔴 Browser polyfill via `Function()`/`eval()`. No real context isolation; shares global scope. | 🔴 Non-functional stub. | Neither offers real `vm` sandboxing. secure-exec polyfill silently runs code in shared scope — not safe for isolation. | |
| 61 | +| **`v8`** | 🔴 Mock heap stats; `serialize`/`deserialize` use JSON instead of V8 binary format (bug). | 🔴 Non-functional stub. | Neither exposes real V8 internals. secure-exec `v8.serialize` silently produces JSON — needs fix to use V8 structured serialization. | |
| 62 | + |
| 63 | +### Crypto and Security |
| 64 | + |
| 65 | +| Module | secure-exec | CF Workers (`nodejs_compat`) | Notes | |
| 66 | +| --- | --- | --- | --- | |
| 67 | +| **`crypto`** | 🔵 Planned. Currently: `getRandomValues()` and `randomUUID()` use host `node:crypto` secure randomness. `subtle.*` throws unsupported errors. | 🟢 Full `node:crypto` surface (hash, HMAC, cipher, sign, verify, key generation). No DSA/DH key pairs, no `ed448`/`x448`, no FIPS mode. | **CF**: Comprehensive crypto support. **secure-exec**: Secure randomness today; full crypto planned. | |
| 68 | +| **Web Crypto** | 🔵 Planned. | 🟢 Available without `nodejs_compat`. | CF has native Web Crypto. | |
| 69 | +| **Fetch globals** | 🟢 `fetch`, `Headers`, `Request`, `Response`. | 🟢 Supported. | | |
| 70 | + |
| 71 | +### Data and Encoding |
| 72 | + |
| 73 | +| Module | secure-exec | CF Workers (`nodejs_compat`) | Notes | |
| 74 | +| --- | --- | --- | --- | |
| 75 | +| **`buffer`** | 🟢 Supported. | 🟢 Supported. | | |
| 76 | +| **`stream`** | 🟢 Supported. | 🟢 Supported. | | |
| 77 | +| **`string_decoder`** | 🟢 Supported. | 🟢 Supported. | | |
| 78 | +| **`zlib`** | 🟢 Supported. | 🟢 Supported; includes Brotli. | CF adds Brotli. | |
| 79 | +| **`querystring`** | 🟢 Supported. | 🟢 Supported. | | |
| 80 | + |
| 81 | +### Utilities and Diagnostics |
| 82 | + |
| 83 | +| Module | secure-exec | CF Workers (`nodejs_compat`) | Notes | |
| 84 | +| --- | --- | --- | --- | |
| 85 | +| **`path`** | 🟢 Supported. | 🟢 Supported. | | |
| 86 | +| **`url`** | 🟢 Supported. | 🟢 Supported. | | |
| 87 | +| **`util`** | 🟢 Supported. | 🟢 Supported. | | |
| 88 | +| **`assert`** | 🟢 Supported. | 🟢 Supported. | | |
| 89 | +| **`events`** | 🟢 Supported. | 🟢 Supported. | | |
| 90 | +| **`module`** | 🟢 `createRequire`, `Module` basics, builtin resolution. | 🟡 Limited surface. | **secure-exec**: CJS/ESM with `createRequire`. | |
| 91 | +| **`console`** | 🟢 Circular-safe bounded formatting; drop-by-default with `onStdio` hook. | 🟢 Supported; output routed to Workers Logs / Tail Workers. | | |
| 92 | +| **`async_hooks`** | ⚪ TBD. | 🔴 Non-functional stub. | | |
| 93 | +| **`perf_hooks`** | ⚪ TBD. | 🟡 Limited surface. | | |
| 94 | +| **`diagnostics_channel`** | ⚪ TBD. | 🟢 Supported. | | |
| 95 | +| **`readline`** | ⚪ TBD. | 🔴 Non-functional stub. | | |
| 96 | +| **`tty`** | 🔴 `isatty()` returns `false`; `ReadStream`/`WriteStream` throw. | 🔴 Stub-like. | Both platforms are essentially non-functional beyond `isatty()`. | |
| 97 | +| **`constants`** | 🟢 Supported. | 🟢 Supported. | | |
| 98 | +| **`punycode`** | Not listed. | 🟢 Supported (deprecated). | | |
| 99 | + |
| 100 | +### Unsupported in Both |
| 101 | + |
| 102 | +| Module | secure-exec | CF Workers | Notes | |
| 103 | +| --- | --- | --- | --- | |
| 104 | +| **`wasi`** | ⛔ Unsupported | ⛔ Unsupported | | |
| 105 | +| **`inspector`** | ⛔ Unsupported | 🟡 Partial (Chrome DevTools) | CF has limited inspector via DevTools. | |
| 106 | +| **`repl`** | ⛔ Unsupported | 🔴 Stub | | |
| 107 | +| **`trace_events`** | ⛔ Unsupported | ⛔ Unsupported | | |
| 108 | +| **`domain`** | ⛔ Unsupported | ⛔ Unsupported | | |
| 109 | + |
| 110 | +--- |
| 111 | + |
| 112 | +## Execution Model Comparison |
| 113 | + |
| 114 | +| Capability | secure-exec | CF Workers / WfP / Dynamic Dispatch | |
| 115 | +| --- | --- | --- | |
| 116 | +| **Isolation** | V8 isolate. | V8 isolate per Worker invocation. | |
| 117 | +| **Permission model** | Deny-by-default for `fs`, `network`, `childProcess`, `env`. Fine-grained per-domain policies. | No granular permission model. WfP adds `request.cf` restriction and cache isolation. | |
| 118 | +| **Memory limits** | Configurable `memoryLimit` (MB). | 128 MB per Worker (platform-managed). | |
| 119 | +| **CPU time limits** | Configurable `cpuTimeLimitMs` with exit code 124. | 10ms (free) / 30s (paid) CPU time; WfP operators can set custom limits. | |
| 120 | +| **Timing mitigation** | `freeze` mode (deterministic clocks) or `off` (real-time). | I/O-gated coarsening — `Date.now()` and `performance.now()` only advance after I/O to mitigate Spectre-class side channels. | |
| 121 | +| **Module loading** | CJS + ESM with package.json `type` field semantics; `node_modules` overlay. | ES modules primary; CJS via `nodejs_compat`; no `node_modules` overlay (bundled at deploy). | |
| 122 | +| **Subprocess execution** | Bound to the system driver; subprocess behavior determined by driver implementation. | Not available. | |
| 123 | +| **Filesystem** | System-driver-determined: host filesystem (permission-gated) or virtual filesystem, depending on driver implementation. Read-only `/app/node_modules` overlay. | Ephemeral VFS only; Durable Objects for persistence. | |
| 124 | +| **Payload limits** | Configurable size limits on sandbox-to-host transfers. | 128 MB script size; request body limits per plan. | |
| 125 | +| **Logging** | Drop-by-default; explicit `onStdio` hook for streaming. | Routed to Workers Logs / Tail Workers. | |
| 126 | + |
| 127 | +--- |
| 128 | + |
| 129 | +## Sources |
| 130 | + |
| 131 | +- [Cloudflare Workers Node.js Compatibility Docs](https://developers.cloudflare.com/workers/runtime-apis/nodejs/) |
| 132 | +- [A Year of Improving Node.js Compatibility (2025)](https://blog.cloudflare.com/nodejs-workers-2025/) |
| 133 | +- [Cloudflare Workers node:http Docs](https://developers.cloudflare.com/workers/runtime-apis/nodejs/http/) |
| 134 | +- [Cloudflare Workers node:fs Docs](https://developers.cloudflare.com/workers/runtime-apis/nodejs/fs/) |
| 135 | +- [Cloudflare Workers node:crypto Docs](https://developers.cloudflare.com/workers/runtime-apis/nodejs/crypto/) |
| 136 | +- [Cloudflare Workers Compatibility Flags](https://developers.cloudflare.com/workers/configuration/compatibility-flags/) |
| 137 | +- [Cloudflare Workers Performance and Timers](https://developers.cloudflare.com/workers/runtime-apis/performance/) |
| 138 | +- [Mitigating Spectre: Cloudflare Workers Security Model](https://blog.cloudflare.com/mitigating-spectre-and-other-security-threats-the-cloudflare-workers-security-model/) |
| 139 | +- [Workers for Platforms Configuration](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/get-started/configuration/) |
| 140 | +- [Workers for Platforms Limits](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/reference/limits/) |
| 141 | +- [How Workers for Platforms Works](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/how-workers-for-platforms-works/) |
| 142 | +- [Dynamic Dispatch Worker](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/configuration/dynamic-dispatch/) |
0 commit comments