Compatibility and limitations
The target is Cloudflare Workers, not a standalone Node.js process. The Node
profile uses workerd 1.20261012.1, compatibility date 2026-10-17, without
additional flags. Other dates and flags are not covered by this profile.
The WebView does not contain workerd or V8; iOS uses its own JavaScript engine.
The earlier workers-capacitor package releases 0.1.0 Preview and the explicitly authorized 0.1.1 Preview follow-up include existing compatibility implementations with the limits below under a version-specific release exception. The explicitly authorized cf-workers-native@0.1.2 Preview retains the documented limitations under its release exception. Inclusion is not a claim of complete Workers or Node.js compatibility.
Native hosts
| Host | Scope |
|---|---|
| iOS embedding | 0.1.2 Preview WorkersIOS SwiftPM product for UIKit/SwiftUI. Close before removing a UIKit controller; SwiftUI dismantling closes automatically. |
| Android embedding | Local Maven SDK publication; no public Maven release. Requires WebView MULTI_PROFILE; one SDK screen at a time, with persistent SDK cookies isolated from host cookies. |
| Capacitor | Existing Capacitor 8 integration, verified with 8.5.3; use this path for general native plugins. |
0.1.2 Preview uses the npm name cf-workers-native; install it once the release
is published. The embedding hosts require matching JS/native versions; they are not included in the earlier
workers-capacitor@0.1.1 release. Both detect incomplete startup after 30 seconds. They reuse the
runtime and build tooling, so they retain the API/framework limits below. See
embedding setup and lifecycle for the platform behavior
and verification scope for host-specific evidence.
Node.js
Whole-Node compatibility is incomplete. Importing a module successfully does not
establish equivalent methods, validation, state, scheduling or engine behavior.
| Area | Behavior and limitations |
|---|---|
| path, querystring, string_decoder, buffer, timers | Implement the pinned Workers profile. Workers stubs remain stubs; for example, matchesGlob reproduces the pinned rejection. |
| HTTP and net | In-memory server dispatch; no OS listening server. Outbound TCP/TLS requires the native transport. |
| fs / fs/promises | Read-only embedded virtual files. Writes, FileHandle, watch and full filesystem semantics are unsupported. |
| module | Limited builtin registry; createRequire loads VFS JSON only. Executable modules must be bundled; arbitrary dynamic resolution is unsupported. |
| process, events, console, util / util/types / sys | Incomplete exports or behavior. Engine introspection, call sites and host-object detection are not equivalent to Workers. |
| crypto and zlib | Dependency implementations do not cover all Workers exports, algorithms, keys or codecs. Do not assume cryptographic or compression parity. |
| TLS and HTTP internals | node:tls is incomplete. _http_common, _http_outgoing, _http_server, _tls_wrap and _stream_wrap fail the import audit. Native TLS transport does not imply Node TLS API compatibility. |
| Streams | A packaged fallback supplies byte streams when the host lacks them. Workers tee cancellation reasons and pipeTo abort timing are not fully reproduced. |
| async_hooks | Build-transformed async functions retain scoped stores. Untransformed native async callbacks reject; arbitrary dynamic code and request-origin isolation are not fully supported. |
| diagnostics_channel | Synchronous channel/store contracts are implemented; async propagation depends on the async-hooks limitations. |
| worker_threads | Workers stubs and local MessagePort behavior, not Node threads. Trusted-event branding, host-object serialization and global identity differ. |
| DNS | DNS-over-HTTPS implementation; synthetic Service Binding/Hyperdrive address overrides are not implemented. |
| Other modules | Implementations and shared contracts exist, but whole-module acceptance remains outstanding. Namespace equality alone is insufficient. |
The exact missing/extra export baseline is maintained in
surface-gaps.json, against
the pinned exports.
Those files are the source of truth; this guide does not duplicate the export list.
Run npm run build, then npm run test:node-inventory --prefix demo to check it.
Behavioral contracts live beside each implementation in src/compat.
Workers non-functional modules do not gain device capabilities: VM isolates,
process spawning, V8 heap access, UDP sockets and an OS terminal are not supplied.
node:test exposes the Workers mock API, not Node's complete test runner.
Workers APIs and bindings
passThroughOnException, local WorkerEntrypoint/RPC, Cache API and HTMLRewriter
are unsupported. Scheduled/queue/workflow lifecycles are not simulated locally.cloudflare:workersis partial. The isolated dispatcher updates a realm-wide
envproxy; direct execution does not populate it. It is not request-local and
is not populated before the first dispatch. Prefer the Fetch Handler argument.
DurableObject is a constructor shell, not a local Durable Objects runtime.Request.cfpreserves supplied values; it does not generate Cloudflare metadata.- Local KV uses device storage without cloud replication or binding RPC.
- D1, Hyperdrive, R2, Service Bindings, Queue producers and
other cloud services execute remotely through the
deployed Worker's HTTP handler. They are not local service implementations.
Local ASSETS is unsupported; use the explicit remote asset policy.
Native networking
HTTP/1.1 framing, redirects and response parsing run in JavaScript/Wasm. Native
code provides TCP/TLS and WebView lifecycle hooks. Each HTTP request uses a
connection with Connection: close; there is no implicit retry after sending.
- HTTPS requires Content-Length or chunked framing. EOF-delimited HTTPS rejects
because the byte bridge cannot distinguish authenticated closure from truncation.
Plain HTTP supports EOF framing. - Trailers are parsed but are not exposed as Fetch response headers. HTTP/2,
protocol upgrades and CONNECT are unsupported by this HTTP/1.1 transport. - Socket reads/writes are bounded at 64 KiB; header text is limited to 64 KiB
across informational/final headers and trailers. Reads follow consumer demand. - Browser execution retains browser CORS/header/cookie restrictions. Native
transport does not promise browser-equivalent SameSite or CSRF protection. - OS termination can stop background work. Selected scenarios cover physical
devices; your application's device behavior, WebView crash recovery and memory
pressure require separate validation.
Document rendering
Remote HTML is rendered at the app-local origin (capacitor://localhost on iOS,
https://workers-sdk.local in the Android embedding host, and normally
https://localhost in a Capacitor Android app). Remote execution keeps server code and
cloud services on the Worker; it does not turn the WebView into that site's origin
or supply every browser authentication feature. Check hydration and interactive
controls, not only a successful HTML response.
Application integration limits
| Feature | Current boundary | Integration guidance |
|---|---|---|
| Better Auth with an inferred client base URL | The pinned flare-stack-blog application fails client initialization on iOS because Better Auth rejects capacitor://localhost. Android's HTTP(S) origin does not hit this rejection. |
An explicit HTTPS authentication endpoint initializes the client, but its full login/cookie flow has not been validated here. Do not assume that setting alone completes migration. See the reproduction. |
| Passkeys / WebAuthn and PRF | Native passkey registration in pknotes fails on both tested platforms. Chromium's virtual authenticator acceptance does not establish native support. | Native credential integration, app/domain association and PRF availability need separate validation. Remote rendering cannot bypass relying-party origin checks. Native support is deferred, not proven technically impossible. See the authentication boundary. |
| Void React Pages | Void / @void/react 1.1.12 covers remote D1 flows and explicitly permitted public GET route execution, including SSR and hydration, in an iOS simulator and Android emulator. Other Void frameworks and whole-Worker local execution are unverified. | Use 1.1.12 or newer for iOS custom-scheme navigation. See Void integration and verification scope. |
| External-browser OAuth | The example verifies synthetic local and public-HTTPS test issuers, PKCE, callback handling and session exchange, including a physical iPhone. Real provider policies, refresh-token storage and cold-start resume are not covered. | Use the provider's native SDK where available. System-browser cookies are not automatically shared with the WebView. See the authentication example. |
| Analytics Engine and other cloud-only services | Analytics Engine executes in Cloudflare; there is no local dataset implementation. Counterscale's live scenario requires a provisioned account, events and an analytics read token. | Keep privileged tokens on the backend and authenticate device requests. The default CI authentication scenario does not exercise live analytics. See Counterscale setup. |
| Image optimization and device performance | The OpenNext fixture covers local workerd and deployed Cloudflare IMAGES, including rendering on a physical iPhone. Performance samples are single Debug runs; physical iOS memory is unmeasured. | Verify production image configuration and measure release-build startup and memory across physical devices before making performance claims. See OpenNext gaps. |
Pinned third-party fixtures exercise specific user flows without editing their
application source; they are not certification of every feature or future version.
Most use local workerd behind HTTPS as the remote backend. Live Analytics Engine and the OpenNext public-HTTPS D1/Images scenario
are explicitly configured exceptions. See the scenario scopes
before relying on a result for a production integration.
See native document rendering for
navigation, form uploads, redirects, trust and lifecycle restrictions. Browser
Service Worker comparisons explicitly expect WebKit to lose replayed POST bodies
and expose redirected: false for synthetic redirects. All other assertions remain
required; these expectations record browser limitations, not supported behavior.
iOS uses a different native scheme bridge. Browser results
are not a substitute for iOS/Android validation.