Skip to content

Latest commit

 

History

History
233 lines (186 loc) · 10.1 KB

cloudflare-compat.md

File metadata and controls

233 lines (186 loc) · 10.1 KB

Cloudflare compatibility

This page lists only the differences from the linked Cloudflare APIs. An entry without a note matches Cloudflare.

  • Yes: implemented, except for the listed differences.
  • Partial: a substantial part is unavailable.
  • Experimental: can change without notice.
  • No: not implemented.

celld rejects an unsupported configuration or API at deployment or first use. An unsupported feature that does not cause an error is a defect.

Services

service status
Workers Yes
Durable Objects Yes
Durable Object Facets Yes
Containers Experimental
Static assets Yes
Cron Triggers Yes
Dynamic Workers Yes
KV Yes
Queues Yes
D1 Yes
Workflows Yes
R2 Yes
Workers AI No
Vectorize No
Hyperdrive No
Browser Rendering No
Email Workers No
Python Workers Partial — fetch handlers on the Pyodide 0.28 runtime line

Runtime APIs

API status
Fetch, Request, Response, and Headers Yes
Bindings Yes
Context Yes
Handlers Yes
RPC Yes
Streams Yes
Encoding Yes
WebSockets Yes
Web Crypto Yes
Web standards Yes
WebAssembly Yes
Performance and timers Yes
Console Yes
Node.js compatibility Partial
Cache Partial
HTMLRewriter Yes
TCP sockets Yes
EventSource Yes
MessageChannel Yes
BroadcastChannel No
  • The cache request option is unavailable.
  • An inbound Request has a cf object without Cloudflare edge fields. celld cannot prove the geolocation, colo, or TLS metadata.
  • celld removes Content-Length from a Worker response, except for a HEAD response.
  • A remote Durable Object call cannot retry after request-body transmission starts because celld keeps no replay copy.
  • A remote Durable Object call waits for a rejected owner generation to change for at most CELLD_OPERATION_DEADLINE_MS.

Only the binding types in the services table are available.

  • passThroughOnException() has no effect because celld has no CDN fallback.
  • ctx.facets is available only inside a Durable Object.

The tail and email handlers are unavailable.

  • An RPC stub cannot cross an isolate boundary.
  • An AbortSignal in a Durable Object RPC call does not cross a node boundary.
  • A remote RPC retries only when the failed peer attempt did not start the method. Use a stable operation ID for an application retry.
  • celld expires an unclaimed and inactive HTTP stream after 60 seconds. A successful stream operation starts a new 60-second period.
  • An expired or unknown stream reports an error instead of EOF.
  • An outbound Worker socket closes when its event and waitUntil work end. A socket returned in the response stays open.
  • Each isolate-polled input queue has a 1 MiB budget for non-terminal frames. A message larger than 1 MiB uses the complete budget.
  • If the isolate stops polling, celld discards unread frames during cleanup. A later pull reports an abnormal close.
  • A WebSocket transport cannot move to a new cell owner. A client must reconnect with the same application operation ID.
  • A tunneled connection forwards the owner's Close without an additional Close. If the owner connection fails between frames before a Close, the ingress sends code 1012. If a frame is incomplete, the ingress closes the transport instead.
  • acceptWebSocket() throws above 90 percent of the V8 heap limit.
  • A response with a WebSocket to a request without Upgrade: websocket fails, as in workerd. A Durable Object's stub.fetch() call then rejects, and an HTTP client receives status 500. The server end of the socket receives a close event with code 1006.
  • A Durable Object's stub.fetch() call rejects when the handler fails, on the owner node and on any other node.
  • HMAC accepts MD5, SHA-1, SHA-224, SHA-256, SHA-384, and SHA-512.
  • ECDSA supports only the P-256 curve with SHA-256.
  • AES-GCM accepts authentication tags from 96 through 128 bits in 8-bit steps.
  • RSA-OAEP accepts SHA-1, SHA-256, SHA-384, and SHA-512. A nonempty label must contain valid UTF-8.
  • A secret key cannot use jwk with exportKey() or wrapKey().
  • Ed25519 signs and verifies, and NODE-ED25519 names the same algorithm. A signature from one spelling verifies under the other.
  • X25519 derives bits and keys. A peer key of a low order gives a shared secret of all zero bytes, so deriveBits() rejects that key instead.
  • An Ed25519 or X25519 public key uses its 32-byte point for the raw format, so importKey() and exportKey() both carry the point alone.

performance.timeOrigin is 0, and performance.now() matches Date.now(). Both clocks advance at an I/O boundary and stay fixed during JavaScript execution.

  • celld implements node:assert, node:async_hooks, node:buffer, node:diagnostics_channel, node:events, node:fs, node:os, node:path, node:stream, node:timers/promises, and node:util.
  • node:diagnostics_channel does not export messages to a tail Worker.
  • node:crypto does not implement Diffie-Hellman, streaming signatures, ciphers, RSA-PSS, or DSA signatures and key generation.
  • KeyObject.toCryptoKey() applies the requested algorithm, extractability, and usages to an asymmetric key.
  • node:zlib implements only the synchronous gzip and deflate functions.
  • node:fs provides access, mkdir, realpath, stat, lstat, and readFile. It exposes an empty, request-local /tmp and a read-only /bundle that contains the Worker modules.
  • The global process matches workerd for each field that it defines, such as process.execPath, process.argv, and process.title. Other fields, such as process.kill and process.features, are undefined.
  • The celld bundler supports a synchronous CommonJS require() of a Node.js built-in module. A raw ESM Worker has no global require().
  • A Node.js built-in module object is writable, so a dependency such as graceful-fs can patch it at load. The patch stays in its isolate.
  • An import of another Node.js module succeeds, but its first call throws an error.

celld provides an always-miss cache because it has no shared edge cache. put() validates and consumes a response but stores nothing, match() returns undefined, and delete() returns false.

  • A socket cannot outlive its event. A Durable Object must reconnect during a later event.
  • celld verifies a TLS server against its bundled Mozilla root store.
  • celld does not block the destination ports that Cloudflare blocks. The fleet network controls the egress policy.

BroadcastChannel

The class exists so that a bundle can load, but its constructor throws.

Compatibility flags

celld honors these compatibility flags:

  • delete_all_deletes_alarm
  • js_rpc
  • fetcher_no_get_put_delete
  • sqlite_vec
  • websocket_standard_binary_type
  • The static-assets navigation flags

celld accepts every other flag without effect. Cloudflare.compatibilityFlags reports only the honored flags.

Wrangler configuration

celld deploy accepts wrangler.jsonc or wrangler.json, not wrangler.toml.

The name value must contain 1 to 63 lowercase ASCII letters, digits, or internal hyphens. It cannot start or end with a hyphen.

The accepted top-level keys:

  • $schema, name, main, and no_bundle
  • compatibility_date and compatibility_flags
  • durable_objects and migrations
  • assets, services, triggers, and vars
  • d1_databases, kv_namespaces, queues, workflows, and r2_buckets
  • worker_loaders and containers
  • define and rules

Any other top-level key, including routes, stops the deployment.

define and rules go to the esbuild run. Each define value is a JavaScript expression, as in Wrangler. A rule type must be Text, Data, or CompiledWasm, and each glob must have the form **/*.ext or *.ext, because esbuild selects a loader by extension. Two rules that give one extension different types stop the deployment. celld already applies CompiledWasm to **/*.wasm, so only that type is valid for .wasm. no_bundle skips esbuild, so no_bundle with define or rules stops the deployment.

An asset-only project can omit main. celld deploy refuses an unsafe asset path, and .assetsignore requires Wrangler.

See Limitations for the operational limits.