Skip to content

90.2% of conformance tests pass.

Scored against workerd's own test suite, probes run side by side with workerd, and 50 real open-source projects. Every number comes from a recorded run. Hover a dot for the test; open a row for the error.

1,670 / 1,851
tests pass
50
real projects run
38
of them unmodified
46 / 66
claims fully hold

Run 2026-11-10 · OpenOrange ea40348 · RivetKit cf8679c · workerd v1.20260903.1

Node.js compat 758 / 771
Web platform 307 / 427
Streams 247 / 254
RPC + entrypoints 154 / 179
Fetch, HTTP, sockets 103 / 107
Durable Objects 87 / 99
Crypto 14 / 14

1,851 boxes, one per scored test, in file order. 1,670 pass. Hover a box for the test and its error. A box the matrix cites opens its row on click.

Why 181 tests fail

  • Behavior differs 112 The test ran and asserted something OpenOrange does differently.
  • Not supported 45 The test needs an API or flag OpenOrange does not implement.
  • Hangs (60s timeout) 11 The test did not finish in 60 seconds.
  • File fails at load 5 The whole test file failed to load, so none of its tests ran.
  • Not-implemented API 5 The test reached a method that throws not-implemented.
  • Bundling fails 2 esbuild could not bundle the test Worker.
  • Not run 1 The test was skipped by the runner.

What is counted

  • workerd's own suite1,602 / 1,774
  • OpenOrange's Durable Object testsCounted under Durable Objects above.68 / 77
  • Not counted399 workerd-only tests that fail on plain Node.js too, 19 the runner could not host, and 9 cut short by a Cloudflare quota.427

What works, by area.

A claim is Works when every recorded result behind it passed, Partial when some did, and Does not work when none did.

Coming soon

On the roadmap. Each row says what happens today and what to do until it lands.

PartialWebSocket hibernationA socket stays open while the object sleeps, and a message wakes the object.Orange emulates hibernation, and real hibernation is coming soon. When an object with an open accepted WebSocket is idle, Orange drops the object and its in-memory state and keeps the socket open. The next message builds a new instance of the object. The Rivet actor stays running the whole time, and it sleeps once the last socket closes. A client stays connected, but the actor does not sleep while it does. 16/19 pass
Why
Rivet 3 has paused WebSocket hibernation, so an actor cannot sleep with a socket open. Orange hibernates the object inside the running actor instead.
What to do
Have clients reconnect on any close, and don't depend on one close code. Keep anything that must survive hibernation or a restart in storage. Close sockets you no longer need, so the actor can sleep.
What to plan for
  • An object with an open socket is always a running actor and does not scale to zero: the actor, its sockets, and their state stay in memory. Before the emulation, an idle awake object cost about 1.1 MB in total, in Orange and the Engine, and each idle socket on one object cost about 0.2 MB. About half of an object's cost stayed after it slept. Measured through orange serve on one machine, with 1,000 idle objects or 1,000 idle sockets on one object, and not measured again with the emulation. It is not a limit.
  • A deploy closes open sockets. On one cluster, each client reconnected on the first try: 1012 on 4 sockets and 1011 on 1. The object is a new instance, and storage survives. In-memory state and the old sockets do not. Whether the object gets webSocketClose during a rollout is not measured.
  • Old and new runners overlap for about 100 s during a rollout, and the Engine can place new objects on the old runner then. Those clients get cut off soon after opening.
  • Under orange dev, a restart closes open sockets with 1012 and a crash with 1006. In both cases a reconnect works and storage survives.
  • Orange pings every network socket every 30 s, because Cloudflare closes idle sockets on pool URLs at 125 s with 1006. With pings, idle sockets stayed open until a rollout closed them at 695 s. A Worker and its objects never see the pings. wrangler dev kept idle sockets open for 360 s with no pings. Real Cloudflare is not measured: its docs say idle sockets get closed and recommend a heartbeat.
  • A client whose connection is cut gives the object webSocketClose with 1006 within about 1 s. A client that stays connected but stops answering pings is closed with 1006 at about 90 s. The object sleeps after both.
  • webSocketClose gets 1001 "gateway disconnected" where a client closed cleanly with 1000. wrangler dev passes the client's code.
  • The object hibernates, but its actor does not sleep with a socket open. Real projects' steps that wait for every actor to sleep fail with Some actor was still awake. The real-project results show each of those steps again under a sleep check that also accepts the emulation.
Results
  • synthetic--do-websocket-hibernation-test AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal: | + actual - expected | Partial 2/3
  • lifecycle: hibernation: a socket stays open through the object's sleep, and a message wakes it Some actor was still awake 45000ms after the last client activity Fail workerd pass
  • lifecycle: open socket: an idle socket stays open past the sleep timeout Pass workerd pass
  • lifecycle: open socket: an idle object drops its in-memory state while its socket stays open Pass workerd pass
  • lifecycle: open socket: the object sleeps after its last socket closes Pass workerd pass
  • lifecycle: open socket: webSocketClose gets the client's close code /closed?room=k4 did not reach the expected state: {"code":1001} Fail workerd pass
  • lifecycle: open socket: a restart closes it with 1012, and a reconnect finds storage Pass workerd fail
  • lifecycle: open socket: a crash closes it with 1006, and a reconnect finds storage Pass workerd pass
  • cluster-websocket: an idle socket on a pool URL, with no pings, closes at 125 s with 1006 Pass
  • cluster-websocket: with pings, idle sockets stay open until a rollout closes them at 695 s Pass
  • cluster-websocket: a rollout closes sockets with 1012, and each client reconnects on the first try Pass
  • cluster-websocket: a socket can also close with 1011 when its object's generation ends Pass
  • cluster-websocket: after a rollout the object is a new instance, and an accepted socket's storage is kept Pass
  • cluster-websocket: a cut client gives the object webSocketClose 1006 within about 1 s, and the object sleeps Pass
  • cluster-websocket: a client that stops answering pings is closed with 1006 at about 90 s, and the object sleeps Pass
  • cluster-websocket: wrangler dev keeps idle sockets open for 360 s with no pings Pass
  • keep-awake-memory: 1,000 objects with one idle socket each cost about 1.1 MB per object Pass
  • keep-awake-memory: 1,000 idle sockets on one object cost about 0.2 MB per socket after a long hold Pass
  • keep-awake-memory: about half of an object's cost stays after it sleeps Pass

SQLite

Durable Object SQL and D1 run on RivetKit's SQLite 3.46. It is a different build from workerd's, so most SQL runs the same and a known set does not. Each row says what to write instead.

WorksJSON, FTS5, RETURNING, UPSERT, window functions, CTEs, STRICT, generated columns, foreign keysAvailable.Same. 7/7 pass
Results
  • sqlite-surface: JSON: json_extract and ->> run Pass workerd pass
  • sqlite-surface: JSON: json_each runs Pass workerd pass
  • sqlite-surface: FTS5: a full-text table can be created and searched Pass workerd pass
  • sqlite-surface: RETURNING and UPSERT run Pass workerd pass
  • sqlite-surface: window functions, CTEs, STRICT, and generated columns run Pass workerd pass
  • sqlite-surface: foreign keys are enforced by default Pass workerd pass
  • sqlite-surface: math: abs() and round() run (core SQLite) Pass workerd pass
WorksRows across sleep and restartRows are durable.Same. Rows survive the object's sleep and an orange dev and Engine restart. 2/2 pass
Results
  • sqlite-surface: rows survive the object's sleep Pass workerd pass
  • sqlite-surface: rows survive a restart Pass workerd pass
Does not workMath functions: cos, sin, sqrt, pow, floor, ceil, and the restAvailable.Fails with no such function: cos, in Durable Object SQL and in D1. 0/5 pass
Why
RivetKit's SQLite is built without the optional math function set.
What to do
Compute in JavaScript after you read the row, or store the computed value in a column. abs() and round() are core SQLite and run.
Results
  • api-tests--sql-test > main Error: no such function: cos at offset 7: SQLITE_ERROR Fail
  • sqlite-surface: math: cos() runs no such function: cos at offset 7: SQLITE_ERROR Fail workerd pass
  • sqlite-surface: math: sqrt() and pow() run no such function: sqrt at offset 7: SQLITE_ERROR Fail workerd pass
  • sqlite-surface: math: floor() and ceil() run no such function: floor at offset 7: SQLITE_ERROR Fail workerd pass
  • sqlite-surface: D1: cos() runs D1_ERROR: no such function: cos at offset 7: SQLITE_ERROR Fail workerd pass
Does not workDELETE ... LIMIT and UPDATE ... LIMITAvailable.Fails with near "LIMIT": syntax error, in Durable Object SQL and in D1. 0/4 pass
Why
RivetKit's SQLite is built without that optional grammar.
What to do
Write DELETE FROM t WHERE rowid IN (SELECT rowid FROM t WHERE ... ORDER BY ... LIMIT n). The same form works for UPDATE, and it runs on Cloudflare too.
Results
  • synthetic--do-sql-test > deleteWithLimit Error: near "LIMIT": syntax error at offset 19: SQLITE_ERROR Fail
  • sqlite-surface: DELETE ... LIMIT runs near "LIMIT": syntax error at offset 35: SQLITE_ERROR Fail workerd pass
  • sqlite-surface: UPDATE ... LIMIT runs near "LIMIT": syntax error at offset 45: SQLITE_ERROR Fail workerd pass
  • sqlite-surface: D1: DELETE ... LIMIT runs D1_ERROR: near "LIMIT": syntax error at offset 26: SQLITE_ERROR Fail workerd pass
WorksThe portable form of DELETE ... LIMITAvailable.Same. WHERE rowid IN (SELECT rowid ... LIMIT n) deletes n rows. 1/1 pass
Results
  • sqlite-surface: workaround: DELETE WHERE rowid IN (SELECT ... LIMIT n) deletes n rows Pass workerd pass
Does not workcursor.rowsRead and D1 meta.rows_readCounts rows the query scanned. Cloudflare bills on it.Counts rows the query returned. A query that scans 5 rows and returns 1 reports 1. 0/4 pass
Why
RivetKit returns finished results and has no scan counters. Orange has no per-row billing to match.
What to do
Do not build cost limits or query-plan checks on this number. To check that a query uses an index, run EXPLAIN QUERY PLAN.
Results
  • synthetic--do-sql-test > readRowCounters AssertionError: 0 == 1 Fail
  • synthetic--do-sql-test > largeRowCounters AssertionError: 0 == 1 Fail
  • sqlite-surface: counters: rowsRead counts scanned rows, not returned rows Expected values to be strictly equal: 1 !== 5 Fail workerd pass
  • sqlite-surface: D1: meta.rows_read counts scanned rows Expected values to be strictly equal: 1 !== 3 Fail workerd pass
Partialcursor.rowsWrittenCounts every row written, including index and trigger writes. Cloudflare bills on it.Counts changed rows from SQLite's change count. Plain inserts match. Index and trigger writes are not counted. 1/4 pass
Why
It comes from sqlite3_changes(), which does not see those writes.
What to do
Use it to learn how many rows a statement changed. Do not use it as a billing estimate.
Results
  • sqlite-surface: counters: rowsWritten counts a plain insert Pass workerd pass
  • sqlite-surface: counters: rowsWritten counts index writes Expected values to be strictly equal: 1 !== 2 Fail workerd pass
  • synthetic--do-sql-test > writeRowCounters AssertionError: Expected values to be loosely deep-equal: | | { Fail
  • synthetic--do-sql-test > triggerRowCounters AssertionError: 1 == 2 Fail
Does not workSQL that Cloudflare's authorizer blocksRejects ATTACH, most PRAGMAs, and internal functions, also inside DEFAULT expressions.They run, against the object's own database. Orange blocks only reserved table names and transaction control. 0/6 pass
Why
RivetKit's SQLite has no authorizer hook. An object's code is trusted app code and each object has its own database, so this does not cross a boundary.
What to do
Code that runs on Cloudflare runs the same here. If you may go back to Cloudflare, keep to its allow-list, because Orange will not stop you.
Results
  • synthetic--do-sql-test > authorizerDefaultExpressions AssertionError: Missing expected exception. Fail
  • synthetic--do-sql-test > internalFunctionsBlocked AssertionError: Missing expected exception. Fail
  • sqlite-surface: authorizer: PRAGMA journal_mode = DELETE is rejected Missing expected rejection. Fail workerd pass
  • sqlite-surface: authorizer: ATTACH is rejected Missing expected rejection. Fail workerd pass
  • sqlite-surface: authorizer: sqlite_compileoption_used() is rejected Missing expected rejection. Fail workerd pass
  • sqlite-surface: authorizer: blocked function in a DEFAULT expression is rejected Missing expected rejection. Fail workerd pass
PartialReserved _cf_ tables, such as _cf_KVReading them fails with access to _cf_KV.key is prohibited.Reading them also fails, with not authorized. 1/3 pass
Why
Orange blocks the names with a text check, not a SQLite authorizer, so the message cannot name the column.
What to do
Treat any error here as a refusal. Do not match on its text.
Results
  • sqlite-surface: reserved names: reading _cf_KV is rejected Pass workerd pass
  • sqlite-surface: reserved names: the _cf_KV error names the column The input did not match the regular expression /access to _cf_KV\.key is prohibited/. Input: 'Error: not authorized' Fail workerd pass
  • synthetic--do-sql-test > regulatorReservedNames AssertionError: The input did not match the regular expression /access to _cf_KV\.key is prohibited/. Input: | | 'Error: not authorized' Fail
WorksRivet's _rivet_ tables in sqlite_masterNo such tables. Code can dump every table it finds, apart from _cf_.Orange leaves RivetKit's _rivet_ tables out of sqlite_master, sqlite_schema, and PRAGMA table_list, so code that walks every table and dumps it works. A query that renames the name and tbl_name columns, or only counts or aggregates rows, still sees them, and reading one fails with not authorized. 2/2 pass
Why
RivetKit keeps its internal tables in the object's own database.
What to do
Do not name your tables _rivet_*. If you count or aggregate over sqlite_master, skip names that start with _rivet_ as well as _cf_.
Results
  • sqlite-surface: reserved names: sqlite_master lists no _rivet_ table Pass workerd pass
  • sqlite-surface: dump: every table sqlite_master lists can be read Pass workerd pass
PartialMulti-statement exec()Bindings apply to the last statement. Only its rows return.Unbound scripts run and return the last statement's rows. Bindings on a script throw OpenOrange does not yet support bindings on multi-statement SQL. 1/2 pass
Why
RivetKit's script call takes no bindings.
What to do
Send a bound statement on its own. For several together, wrap them in ctx.storage.transactionSync().
Results
  • sqlite-surface: multi-statement: only the last statement's rows return Pass workerd pass
  • sqlite-surface: multi-statement: bindings apply to the last statement OpenOrange does not yet support bindings on multi-statement SQL Fail workerd pass
WorksBEGIN and COMMIT in SQL, empty-result columnNamesBEGIN is rejected, and an empty result keeps its columns.Same. 2/2 pass
Results
  • sqlite-surface: BEGIN in SQL is rejected, as on Cloudflare Pass workerd pass
  • sqlite-surface: empty result keeps columnNames Pass workerd pass
Partialworkerd's own SQL testsapi-tests--sql-test and the do-sql tests ported from workerd's C++ tests. What fails is listed in the rows above. 0/2 pass
Results
  • synthetic--do-sql-test AssertionError: Missing expected exception. Partial 7/15
  • api-tests--sql-test Error: no such function: cos at offset 7: SQLITE_ERROR Partial 8/9

Durable Objects

Each object is one Rivet Actor. Storage, alarms, RPC, and WebSockets follow workerd's behaviour, checked against workerd's own tests.

WorksStorage API: get, put, list, delete, transaction, sync KVAvailable.Same, stored in the object's SQLite. 4/4 pass
Results
  • synthetic--do-storage-test Pass 24/24
  • api-tests--actor-kv-test Pass 1/1
  • api-tests--sync-kv-test Pass 1/1
  • lifecycle: storage: a value survives the object's sleep Pass workerd pass
WorksKV-backed classes (new_classes)A separate storage backend with no SQL.Accepted, and stored in SQLite like every other class, so the class can also use SQL. There is no import of data from a Cloudflare KV-backed object. 2/2 pass
What to do
New code runs unchanged. To move a live object off Cloudflare, read its data out through its own API.
Results
  • lifecycle: KV-backed class: the storage API keeps a value Pass workerd pass
  • lifecycle: KV-backed class: SQL is available Pass workerd fail
WorksObject ids and input gatesAvailable.Same. 2/2 pass · 1 not run
Results
  • synthetic--do-id-test Pass 2/2
  • synthetic--do-input-gate-test Pass 5/5
  • api-tests--actor-block-concurrency-depth-test Not run
WorksAlarmsAn alarm fires on time, wakes a sleeping object, and survives a restart.Same, when the process is up at the alarm's time. 4/4 pass
Results
  • synthetic--do-alarm-test Pass 17/17
  • lifecycle: alarm: fires on time Pass workerd pass
  • lifecycle: alarm: wakes a sleeping object with no request Pass workerd pass
  • lifecycle: alarm: a future alarm survives a restart Pass workerd pass
WorksAn alarm due while the process is downFires when the runtime comes back.Same. It fires after a restart, with no request. 1/1 pass
Results
  • lifecycle: alarm: an alarm due while the process is down fires after a restart, with no request Pass workerd pass
PartialRPC and entrypointsAvailable.Stubs, WorkerEntrypoint, RpcTarget, and streams work. Calls from one process to one object keep the order they were made in, whichever stub made them, as in workerd. Other failing tests are in the report. 2/3 pass
Results
  • workerd tests: RPC + entrypoints Partial 154/179
  • api-tests--request-signal-enabled > abortIfClientAbandonsRequest Pass
  • api-tests--request-signal-enabled > abortedRequestDoesNotAbortSubrequest Pass
WorksWebSockets through an objectAvailable.Same, while the object stays awake. 2/2 pass
Results
  • synthetic--do-websocket-test Pass 11/11
  • workers-chat-demo: two clients chat in a room, and history is kept Pass
WorksAn object that closes its own socket can still sleepAvailable.Same. 1/1 pass
Results
  • lifecycle: hibernation: an object that closes its own socket still sleeps Pass workerd pass
WorksDurable Object facetsAvailable.A child Rivet Actor per facet, with abort, class swap, and delete. 1/1 pass
Results
  • example: facets-loader Pass
PartialA runner whose Engine connection goes half-openNot applicable: Cloudflare has no runner to reconnect.A closed socket reconnects. A socket that stays open and stops carrying data never does: the node leaves the pool, the runner logs nothing, and Durable Object calls return 500 after 45 s. Reproduced locally with a TCP proxy. Not proven on a cluster: one cluster outage had matching symptoms. 1/2 pass
Why
A RivetKit bug: the envoy client's read loop has no deadline, so nothing notices silence while connected.
What to do
Until the fix ships, watch the node count in /pools/{pool}/nodes and restart a runner that has no node.
Results
  • runner-half-open: a runner reconnects after its Engine socket closes Pass
  • runner-half-open: a runner reconnects after its Engine socket stops carrying data 75 s after the fault: 0 nodes, object call 500 in 45013ms Fail

Bindings

Each binding runs on Rivet Actors unless noted. The scaling table below says how each one grows.

WorksKVEventually consistent, with a global edge cache.Strongly consistent. Reads never see stale values, and cacheStatus is always null. 1/1 pass
Results
  • example: kv Pass
WorksD1Available.prepare, batch, and migrations work, on the SQLite build above. Everything in the SQLite section applies. 2/2 pass
Results
  • example: d1-migrations Pass
  • sqlite-surface: D1: batch() runs statements in order Pass workerd pass
WorksR2Available.On an S3-compatible store per bucket, or in actor SQLite when none is set. In actor SQLite, Rivet's storage limit for one actor bounds a bucket. SSE-C keys throw. 1/1 pass
What to do
In production, set ORANGE_R2_<BUCKET>_S3_*.
Results
  • example: r2 Pass
WorksQueuesAvailable.Delays, retries, dead letter queues, and batches work. One batch at a time per queue. 1/1 pass
Results
  • example: queues Pass
WorksWorkflowsAvailable.Steps, retries, sleeps, events, terminate, pause, resume, and restart work. terminate cannot stop a step callback that is already running. 6/6 pass
Results
  • example: workflows Pass
  • lifecycle: Workflows: create, step, status, complete Pass workerd pass
  • lifecycle: Workflows: sendEvent releases a waiting instance Pass workerd pass
  • lifecycle: Workflows: terminate() ends a waiting instance Pass workerd pass
  • lifecycle: Workflows: pause() and resume() Pass workerd pass
  • lifecycle: Workflows: restart() runs a finished instance again Pass workerd pass
WorksRate LimitingLocal to each edge location, and approximate.One exact counter per namespace. 1/1 pass
Results
  • example: rate-limiting Pass
WorksCache APIAvailable.caches.default and named caches work, on Miniflare's freshness rules. Set ORANGE_CACHE=off to turn it off. 1/1 pass
Results
  • example: cache-api Pass
WorksCron TriggersAvailable.Full Cloudflare cron syntax, including LW and #. 1/1 pass
Results
  • example: cron Pass
WorksWorkers AIModels on Cloudflare's network.Any OpenAI-compatible provider. It needs your key, and @cf/ model names need a mapping in ORANGE_AI_MODELS. 1/1 pass
Results
  • example: workers-ai Pass
WorksSandboxesOn Cloudflare Containers.@cloudflare/sandbox on your choice of provider, set by ORANGE_SANDBOX_PROVIDER. 2/2 pass
Results
  • example: sandbox Pass
  • example: sandbox-v1 Pass
WorksService bindings and dispatch namespacesAvailable.Across the Workers of one orange dev session. orange deploy ships one Worker at a time, so a binding to another Worker has nothing to reach on a pool. 2/2 pass
Results
  • example: multi-worker Pass
  • example: rpc-entrypoints Pass
Worksconnect() through a service binding to another WorkerAvailable.A call reaches the connect() handler in another Worker of the orange dev session. 1/1 pass
Results
  • api-tests--connect-handler-test > localAddressViaServiceBinding Pass
Worksqueue() and scheduled() on a service bindingAvailable.Both run the handler and report its outcome. queue() reads workerd's serializedBody format, and a crafted payload fails the event. A serializedBody holding a stream, stub, or abort signal also fails the event. A decoded Headers isn't immutable, because Orange has no Headers guard. Unlike connect(), both calls reject when the binding points at another Worker of an orange dev session. 2/2 pass
What to do
In orange dev, call queue() and scheduled() on a binding to the same Worker. Send plain values in serializedBody.
Results
  • api-tests--deserialize-hardening-test Pass 6/6
  • api-tests--queue-metadata-test > queue-metadata-test Pass
WorksSend Email (send_email)Sends mail from a Worker. destination_address and the allow lists limit who it can reach.Sends through the SMTP server in ORANGE_EMAIL_SMTP_URL. Both an EmailMessage and the message object work, with Cc, Bcc, and attachments. A recipient outside the address limits is refused before anything is sent. Without the variable, send() throws an error that names it. 4/4 pass
What to do
Set ORANGE_EMAIL_SMTP_URL to your mail provider's SMTP endpoint.
What to plan for
  • You bring the SMTP provider. Orange does not check sender domains or verified destinations. Your provider does its own checks.
Results
  • email: Send Email: an EmailMessage with its own MIME arrives over SMTP Pass
  • email: Send Email: a message object arrives with its Cc, Bcc, and attachment Pass
  • email: Send Email: a recipient outside allowed_destination_addresses is refused, and nothing is sent Pass
  • agentic-inbox: a sent email and a threaded reply are delivered over SMTP through the send_email binding Pass
WorksInbound email: email(), forward(), and reply()Email Routing delivers mail to the email() handler, and message.forward() and message.reply() send it on.A message POSTed to /cdn-cgi/handler/email runs email(): raw MIME, or a SendGrid or Mailgun inbound webhook. forward() and reply() send through ORANGE_EMAIL_SMTP_URL, and setReject() answers 400. With ORANGE_EMAIL_INBOUND_SECRET set, a wrong secret gets 401 and email() does not run. orange serve serves the route only when the secret is set. The evidence here runs on orange dev. 7/7 pass
Why
Email Routing itself, Cloudflare's MX and routing rules, is Cloudflare-only. Orange has no mail server, so something else must receive the mail and POST it.
What to do
Point your mail provider's inbound webhook at /cdn-cgi/handler/email, with the secret.
What to plan for
  • Email Routing is Cloudflare-only. A provider such as SendGrid or Mailgun must receive the mail.
Results
  • email: Inbound email: a POSTed message runs email(), and forward() sends it on over SMTP Pass
  • email: Inbound email: reply() sends the Worker's reply, with In-Reply-To Pass
  • email: Inbound email: setReject() answers 400 Pass
  • email: Inbound email: a wrong secret gets 401, and email() does not run Pass
  • vmail: an inbound email goes through email() into the mailbox, and the mailbox lists it Pass
  • vmail: an email to a mailbox that was never created is rejected Pass
  • agentic-inbox: an inbound email goes through the Worker's email() handler into the inbox Pass
WorksBrowser Rendering (browser)@cloudflare/puppeteer drives a browser that Cloudflare runs.@cloudflare/puppeteer 1.x works unchanged against the Chrome in ORANGE_BROWSER_CDP_URL: pages, screenshots, and sessions, with requests at once each in their own page. browser.close() closes only that session's pages. Without the variable, fetch() throws an error that names it. 4/4 pass
What to do
Run a headless Chrome that the runner can reach, and set ORANGE_BROWSER_CDP_URL to it.
What to plan for
  • You run the browser. All sessions share it, so they share cookies and storage.
  • A session ends with its WebSocket, so connect() cannot rejoin a session after disconnect().
  • keep_alive, location, and recording are accepted and ignored.
Results
  • browser-rendering: launch() opens a page in the configured browser, reads it, and takes a PNG screenshot Pass
  • browser-rendering: two requests at once each read their own page Pass
  • browser-rendering: browser.close() ends the session, and the next launch still works Pass
  • browser-rendering: connect() to a session that is in use is refused Pass
Does not workVectorize, Images, Pipelines, mTLSAvailable.Not implemented. Config loads, and a call throws a clear error that names the binding. 0/4 pass
What to do
Call your provider's HTTP API with fetch().
Results
  • stub-bindings: Vectorize: query() runs Vectorize binding "VECTORIZE" is not supported by OpenOrange. See the OpenOrange bindings documentation for supported bindings. false !== true Fail
  • stub-bindings: Images: info() runs Images binding "IMAGES" is not supported by OpenOrange. See the OpenOrange bindings documentation for supported bindings. false !== true Fail
  • stub-bindings: Pipelines: send() runs Pipelines binding "PIPELINE" is not supported by OpenOrange. See the OpenOrange bindings documentation for supported bindings. false !== true Fail
  • stub-bindings: mTLS certificates: fetch() runs mTLS certificate binding "CERT" is not supported by OpenOrange. See the OpenOrange bindings documentation for supported bindings. false !== true Fail
Not runContainersAvailable.No container runtime. The config loads with a warning. A class listed under containers gets a ctx.container that runs only Cloudflare Sandbox images, on ORANGE_SANDBOX_PROVIDER. Not run here. —

Runtime

Workers run on Node.js with workerd-shaped globals. These counts are workerd's own test suite, scored only where workerd itself passes.

PartialNode.js compatibilityStock Node.js built-ins. Tests that only pass because of a workerd stub do not count. 0/1 pass
Results
  • workerd tests: Node.js compat Partial 758/771
PartialWeb platformThe report groups the failures by cause. 0/1 pass
Results
  • workerd tests: Web platform Partial 307/427
PartialStreamsSee the report for the failing tests. 0/1 pass
Results
  • workerd tests: Streams Partial 247/254
PartialFetch, HTTP, socketsSee the report for the failing tests. 0/1 pass
Results
  • workerd tests: Fetch, HTTP, sockets Partial 103/107
WorksCryptoAll scored tests pass. 1/1 pass
Results
  • workerd tests: Crypto Pass 14/14
PartialCompatibility flagsA Worker's flags and date select its behaviour.Orange applies request_signal_passthrough and the assets navigation flags. The rest of the profile stays fixed, and orange dev warns about a flag it ignores. Tests that need a different flag value fail. 2/4 pass
What to do
Read the warning from orange dev, and don't depend on a flag it names.
Results
  • api-tests--request-signal-passthrough > requestPassedOverRpcIncludesSignal Pass
  • api-tests--request-signal-enabled > requestPassedOverRpcDoesNotIncludeSignal Pass
  • api-tests--http-test > cacheMode AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: | | true !== false Fail
  • api-tests--js-rpc-test > sendStubOverRpc AssertionError [ERR_ASSERTION]: Missing expected rejection (Error). Fail

Past Cloudflare's limits.

Where OpenOrange does more than the platform allows. Each row is a probe that ran.

WorksCPU time per request10 ms on Free. 30 s by default on Paid, up to 5 minutes.No limit. An object ran 35 s of CPU in one request. 1/1 pass
Results
  • beyond-limits: a Durable Object runs 35 s of CPU in one request Pass
WorksMemory128 MB per isolate.The container's memory. An object held 512 MiB between requests. 1/1 pass
Results
  • beyond-limits: a Durable Object holds 512 MiB between requests Pass
WorksSubrequests per request50 on Free. A configurable limit on Paid.No limit. One request made 2,000. 1/1 pass
Results
  • beyond-limits: one request makes 2,000 subrequests Pass
WorksRequest body size100 MB on Free and Pro, up to 500 MB on Enterprise.No limit. A 600 MiB body streamed through. 1/1 pass
Results
  • beyond-limits: a 600 MiB request body streams through Pass
WorksGlobal scope time1 s, or the deploy fails.No limit. A Worker with a 1.5 s global scope started. 1/1 pass
Results
  • beyond-limits: a Worker whose global scope runs for 1.5 s starts Pass
WorksSQLite size limits2 MB per value, 100 KB per statement, 100 bound parameters, 100 columns.SQLite's own limits. A 5 MiB BLOB, a 300 KB statement, 200 parameters, and 200 columns all ran. workerd refuses each one. 4/4 pass
Results
  • beyond-surface: SQLite: a 5 MiB BLOB Pass workerd fail
  • beyond-surface: SQLite: a 300 KB statement Pass workerd fail
  • beyond-surface: SQLite: 200 bound parameters Pass workerd fail
  • beyond-surface: SQLite: a table with 200 columns Pass workerd fail
Workssqlite_version()Rejected: not authorized to use function.Runs. 1/1 pass
Results
  • sqlite-surface: sqlite_version() runs Pass workerd fail
WorksReal Node.js APIsnode:child_process throws not implemented, and node:net cannot listen.Stock Node.js. A Worker ran a host command and listened on a port. The container is the isolation boundary, as for any Rivet Actor. 3/3 pass
Results
  • beyond-surface: node:child_process runs a host command Pass workerd fail
  • beyond-surface: node:fs writes and reads a real file Pass workerd pass
  • beyond-surface: node:net listens on a port Pass workerd fail
Not runStorage per object10 GB.No Orange limit. Not run at this size. —

What each binding scales by.

The unit that adds capacity, and what runs one of them.

WorksDurable ObjectsObject IDOne actor per object id. Add ids to add capacity. 1/1 pass
WorksWorkflowsInstanceOne actor per instance. 1/1 pass
WorksD1DatabaseOne actor per database. A busy database is one actor, so split by tenant for more. 1/1 pass
WorksKVNamespaceOne actor per namespace, so one namespace does not fan out across actors. Split namespaces for more. 1/1 pass
WorksQueuesQueueOne actor per queue, delivering one batch at a time. 1/1 pass
WorksRate LimitingNamespaceOne actor per namespace_id, which holds every key's counter. 1/1 pass
WorksCacheCache nameOne actor per cache name. caches.default is one actor, so busy traffic should use named caches. 2/2 pass
WorksR2S3 or bucketWith S3 set, as far as your S3 store goes. Without it, one actor per bucket. 2/2 pass
Not runWorkersRunner countStateless requests go to any runner in the pool. Not measured across runners here. —

50 real projects.

Open-source Cloudflare Workers with Durable Objects, run on OpenOrange as published. 38 needed no change.

26
steps failed · WebSocket hibernation not available on Rivet 3
2
steps failed · The project's own code
1
steps failed · Test environment
Workstldraw/tldraw 51,216 stars · 1 class · 1 change 6/6
Source
tldraw/tldraw at aae1c5d, Worker in apps/bemo-worker. Durable Objects: BemoDO using blockConcurrencyWhile, storage.get, storage.put, storage.getAlarm, storage.setAlarm, alarm, WebSocketPair.
Changes
  • Adds a top-level BEMO_BUCKET r2_buckets entry to apps/bemo-worker/wrangler.toml The project declares the bucket only under [env.*], and its dev script selects --env dev. orange dev runs the top-level config.
Partialreactive-resume/reactive-resume 45,283 stars · 1 class · unmodified Test environment an account signs up and gets a session from PostgreSQL through Hyperdrive Expected values to be strictly equal: 500 !== 200 4/5
Source
reactive-resume/reactive-resume at f7b0eee, Worker in .. Durable Objects: Coordination using storage.kv, storage.transactionSync, storage.setAlarm, storage.deleteAll, alarm, acceptWebSocket, getWebSockets.
Changes
None. The project ran as published.
Failed steps
  • an account signs up and gets a session from PostgreSQL through Hyperdrive Test environment — It needs PostgreSQL, which this machine does not have. With postgres:16-alpine, its 67 migrations, and the connection string in this project.json, the step passed in a separate run. Expected values to be strictly equal: 500 !== 200
Needs secretssupermemoryai/supermemory 31,518 stars · 1 class · unmodified Needs SUPERMEMORY_OAUTH_ACCESS_TOKEN 3/4
Source
supermemoryai/supermemory at 16ed414, Worker in apps/mcp. Durable Objects: SpaceState using storage.get, storage.put, storage.delete, storage.transaction, storage.setAlarm.
Changes
None. The project ran as published.
Credentials a real deployment would set
SUPERMEMORY_OAUTH_ACCESS_TOKEN
Needs secretscloudflare/cloudflare-os 11,666 stars · 5 classes · unmodified Needs AI provider API key 8/9
Source
cloudflare/cloudflare-os at b533f8a, Worker in packages/workshop-backend. Durable Objects: UserDurableObject, OverseerDurableObject, AdminSettings, PendingLogin, UserDirectoryDurableObject using storage.sql, RPC, ctx.exports, getByName, RPC callbacks.
Changes
None. The project ran as published.
Credentials a real deployment would set
AI provider API key
Workscloudflare/computer 9,786 stars · 1 class · unmodified 6/6
Source
cloudflare/computer at b995d86, Worker in examples/worker-shell. Durable Objects: ContainerExample using storage.sql, rpc, ctx.exports, worker_loaders.
Changes
None. The project ran as published.
Needs secretscloudflare/agentic-inbox 8,589 stars · 3 classes · 2 changes Needs OPENROUTER_API_KEY 9/10
Source
cloudflare/agentic-inbox at 48039bb, Worker in .. Durable Objects: MailboxDO, EmailAgent, EmailMCP using storage.sql, RPC methods, agents Agent, McpAgent, AIChatAgent, WebSocket.
Changes
  • Sets POLICY_AUD and TEAM_DOMAIN in wrangler.jsonc vars, with TEAM_DOMAIN pointing at a local JWKS server that the scenario runs The production build refuses every request without Cloudflare Access settings. The scenario signs real Access JWTs, and the Worker verifies them through its own jose code. The Vite build writes build/server/wrangler.json, so .dev.vars written after the build cannot reach it.
  • A build step removes "legacy_env":true from the generated build/server/wrangler.json Orange's wrangler 4.129.0 refuses the field that the project's Vite plugin 1.29.0 writes, and orange dev exits at boot. Removing it shows what lies behind that error. Repro: repros/generated-legacy-env.
Credentials a real deployment would set
OPENROUTER_API_KEY
Works, emulated hibernationjsfiddle/togetherjs 6,997 stars · 2 classes · unmodified WebSocket hibernation not available on Rivet 3 two sockets stay open while a room hibernates, and a message wakes it Some actor was still awake 60 s after the last client activity the registry still knows a room after every object sleeps Some actor was still awake 60 s after the last client activity 5/7
Source
jsfiddle/togetherjs at 77eada2, Worker in hub-worker. Durable Objects: Room, Registry using acceptWebSocket, getWebSockets, serializeAttachment, deserializeAttachment, storage.get, storage.put, rpc.
Changes
None. The project ran as published.
Failed steps
  • two sockets stay open while a room hibernates, and a message wakes it WebSocket hibernation not available on Rivet 3 — WebSocket hibernation is not available on Rivet 3. Orange emulates it: it drops the idle object and keeps its sockets open, but the Rivet actor does not sleep while a socket is open. This step waits for every actor to sleep, so it fails with: Some actor was still awake. Some actor was still awake 60 s after the last client activity With emulated hibernation, this step passes. It still counts as failed.
  • the registry still knows a room after every object sleeps WebSocket hibernation not available on Rivet 3 — WebSocket hibernation is not available on Rivet 3. Orange emulates it: it drops the idle object and keeps its sockets open, but the Rivet actor does not sleep while a socket is open. This step waits for every actor to sleep, so it fails with: Some actor was still awake. Some actor was still awake 60 s after the last client activity With emulated hibernation, this step passes. It still counts as failed.
Works, emulated hibernationLouis-CFM/coucou 6,926 stars · 1 class · unmodified WebSocket hibernation not available on Rivet 3 an idle room hibernates, and the next frame still reaches the peer Some actor was still awake 45000ms after the last client activity 6/7
Source
Louis-CFM/coucou at 7436363, Worker in android/relay. Durable Objects: Room using acceptWebSocket, getWebSockets, serializeAttachment, deserializeAttachment, setWebSocketAutoResponse.
Changes
None. The project ran as published.
Failed steps
  • an idle room hibernates, and the next frame still reaches the peer WebSocket hibernation not available on Rivet 3 — WebSocket hibernation is not available on Rivet 3. Orange emulates it: it drops the idle object and keeps its sockets open, but the Rivet actor does not sleep while a socket is open. This step waits for every actor to sleep, so it fails with: Some actor was still awake. Some actor was still awake 45000ms after the last client activity With emulated hibernation, this step passes. It still counts as failed.
Works, emulated hibernationsadmann7/tablecn 6,371 stars · 1 class · unmodified WebSocket hibernation not available on Rivet 3 a client stays connected while the room hibernates, and its next edit is acknowledged Some actor was still awake 45000ms after the last client activity 5/6
Source
sadmann7/tablecn at 2d74ac5, Worker in .. Durable Objects: SkaterRoom using storage.get, storage.put, storage.delete, storage.deleteAll, storage.setAlarm, storage.deleteAlarm, acceptWebSocket, getWebSockets, serializeAttachment.
Changes
None. The project ran as published.
Failed steps
  • a client stays connected while the room hibernates, and its next edit is acknowledged WebSocket hibernation not available on Rivet 3 — WebSocket hibernation is not available on Rivet 3. Orange emulates it: it drops the idle object and keeps its sockets open, but the Rivet actor does not sleep while a socket is open. This step waits for every actor to sleep, so it fails with: Some actor was still awake. Some actor was still awake 45000ms after the last client activity With emulated hibernation, this step passes. It still counts as failed.
Partialluolangaga/tubatools 6,035 stars · 1 class · unmodified The project's own code an SDP offer sent on one device's socket reaches the other device No WebSocket message within 20000ms 5/6
Source
luolangaga/tubatools at 15dcb42, Worker in cloudflare-worker. Durable Objects: GroupRoom using storage.list, storage.put, storage.deleteAll, acceptWebSocket, WebSocket.addEventListener.
Changes
None. The project ran as published.
Failed steps
  • an SDP offer sent on one device's socket reaches the other device The project's own code — GroupRoom accepts with acceptWebSocket but listens with addEventListener and defines no webSocketMessage, so the frame is never relayed. Read from the code and the hibernation API contract, not run on Cloudflare. No WebSocket message within 20000ms
Partialcloudflare/agents 5,942 stars · 5 classes · unmodified WebSocket hibernation not available on Rivet 3 a client socket stays open while the agent hibernates, and a call wakes it Some actor was still awake 45000ms after the last client activity 6/8
Source
cloudflare/agents at 455b47e, Worker in examples/playground. Durable Objects: StateAgent, ScheduleAgent, SqlAgent, SupervisorAgent, ChildAgent using storage.sql, setAlarm, acceptWebSocket, serializeAttachment, rpc.
Changes
None. The project ran as published.
Failed steps
  • a client socket stays open while the agent hibernates, and a call wakes it WebSocket hibernation not available on Rivet 3 — WebSocket hibernation is not available on Rivet 3. Orange emulates it: it drops the idle object and keeps its sockets open, but the Rivet actor does not sleep while a socket is open. This step waits for every actor to sleep, so it fails with: Some actor was still awake. Some actor was still awake 45000ms after the last client activity With emulated hibernation, this step passes. It still counts as failed.
Credentials a real deployment would set
Workers AI (remote AI binding)
Needs secretscloudflare/vibesdk 5,451 stars · 6 classes · 1 change Needs ANTHROPIC_API_KEY, CLOUDFLARE_AI_GATEWAY_TOKEN 5/6
Source
cloudflare/vibesdk at 32c9e42, Worker in .. Durable Objects: DORateLimitStore, ThinkAgent, SpaceDO, CodeGeneratorAgent, UserAppSandboxService, UserSecretsStore using storage.get, storage.put, RPC methods, agents Agent.
Changes
  • Two imports in worker/api/controllers/artifacts/controller.ts use the relative path that the wrangler.jsonc alias names Orange ignores the Wrangler alias field, and orange dev exits with: No such module "artifacts-viewer". The patch shows what lies behind that error. Repro: repros/wrangler-alias-field.
Credentials a real deployment would set
ANTHROPIC_API_KEY, CLOUDFLARE_AI_GATEWAY_TOKEN
Works, emulated hibernationEpicenterHQ/epicenter 4,840 stars · 1 class · unmodified WebSocket hibernation not available on Rivet 3 two sockets stay open while the authority hibernates, and a push wakes it Some actor was still awake 60 s after the last client activity 5/6
Source
EpicenterHQ/epicenter at 7cc869b, Worker in apps/sync-lab. Durable Objects: SyncLabAuthority using storage.sql.exec, storage.transactionSync, acceptWebSocket, getWebSockets, serializeAttachment, deserializeAttachment, rpc.
Changes
None. The project ran as published.
Failed steps
  • two sockets stay open while the authority hibernates, and a push wakes it WebSocket hibernation not available on Rivet 3 — WebSocket hibernation is not available on Rivet 3. Orange emulates it: it drops the idle object and keeps its sockets open, but the Rivet actor does not sleep while a socket is open. This step waits for every actor to sleep, so it fails with: Some actor was still awake. Some actor was still awake 60 s after the last client activity With emulated hibernation, this step passes. It still counts as failed.
Needs secretscloudflare/mcp-server-cloudflare 4,441 stars · 1 class · unmodified Needs CLOUDFLARE_CLIENT_ID, CLOUDFLARE_CLIENT_SECRET 4/5
Source
cloudflare/mcp-server-cloudflare at a21972e, Worker in apps/dex-analysis. Durable Objects: WarpDiagReader using RPC methods on a stub, instance memory as a per-capture cache.
Changes
None. The project ran as published.
Credentials a real deployment would set
CLOUDFLARE_CLIENT_ID, CLOUDFLARE_CLIENT_SECRET
Works, emulated hibernationshuaiplus/nodewarden 4,093 stars · 2 classes · unmodified WebSocket hibernation not available on Rivet 3 a client stays connected while the hub hibernates, and the next notification reaches it Some actor was still awake 45 s after the last client activity 6/7
Source
shuaiplus/nodewarden at fbc0e65, Worker in .. Durable Objects: NotificationsHub, BackupTransferRunner using acceptWebSocket, getWebSockets, serializeAttachment, deserializeAttachment, setWebSocketAutoResponse, storage.put, storage.get, storage.delete, storage.list, storage.transaction, storage.setAlarm.
Changes
None. The project ran as published.
Failed steps
  • a client stays connected while the hub hibernates, and the next notification reaches it WebSocket hibernation not available on Rivet 3 — WebSocket hibernation is not available on Rivet 3. Orange emulates it: it drops the idle object and keeps its sockets open, but the Rivet actor does not sleep while a socket is open. This step waits for every actor to sleep, so it fails with: Some actor was still awake. Some actor was still awake 45 s after the last client activity With emulated hibernation, this step passes. It still counts as failed.
Partialopen-inspect/background-agents 3,450 stars · 1 class · 1 change WebSocket hibernation not available on Rivet 3 a subscribed client stays connected while the session hibernates Some actor was still awake 45000ms after the last client activity 5/7
Source
open-inspect/background-agents at cd63f81, Worker in packages/control-plane. Durable Objects: SessionDO using storage.sql, acceptWebSocket, getWebSockets, setAlarm, alarm.
Changes
  • packages/control-plane/wrangler.jsonc: adds migrations_dir for the DB binding, pointing at terraform/d1/migrations Production is deployed with Terraform, which applies these migrations. The repository's Wrangler config is the one its Worker tests use, and it has no migrations_dir.
Failed steps
  • a subscribed client stays connected while the session hibernates WebSocket hibernation not available on Rivet 3 — WebSocket hibernation is not available on Rivet 3. Orange emulates it: it drops the idle object and keeps its sockets open, but the Rivet actor does not sleep while a socket is open. This step waits for every actor to sleep, so it fails with: Some actor was still awake. Some actor was still awake 45000ms after the last client activity With emulated hibernation, this step passes. It still counts as failed.
Credentials a real deployment would set
ANTHROPIC_API_KEY, MODAL_TOKEN_ID, MODAL_TOKEN_SECRET
Works, emulated hibernationchuspeeism/dashi-taskboard 3,441 stars · 1 class · unmodified WebSocket hibernation not available on Rivet 3 a board socket stays open while the hub hibernates, and a later write reaches it Some actor was still awake 45000ms after the last client activity 5/6
Source
chuspeeism/dashi-taskboard at 9aa1f4e, Worker in .. Durable Objects: RealtimeHub using acceptWebSocket, getWebSockets, storage.list, storage.put, storage.delete.
Changes
None. The project ran as published.
Failed steps
  • a board socket stays open while the hub hibernates, and a later write reaches it WebSocket hibernation not available on Rivet 3 — WebSocket hibernation is not available on Rivet 3. Orange emulates it: it drops the idle object and keeps its sockets open, but the Rivet actor does not sleep while a socket is open. This step waits for every actor to sleep, so it fails with: Some actor was still awake. Some actor was still awake 45000ms after the last client activity With emulated hibernation, this step passes. It still counts as failed.
Needs secretsForward-Future/loopy 3,216 stars · 3 classes · unmodified Needs GITHUB_OAUTH_CLIENT_ID, GITHUB_OAUTH_CLIENT_SECRET, HERENOW_API_KEY, TURNSTILE_SECRET_KEY 5/7
Source
Forward-Future/loopy at 75966cb, Worker in loop-library/worker. Durable Objects: LoopCatalog, VoteStore, FormGuard using storage.sql.exec, storage.transactionSync, storage.get, storage.put, storage.setAlarm.
Changes
None. The project ran as published.
Credentials a real deployment would set
GITHUB_OAUTH_CLIENT_ID, GITHUB_OAUTH_CLIENT_SECRET, HERENOW_API_KEY, TURNSTILE_SECRET_KEY
Works, emulated hibernationaudreyt/ethercalc 3,062 stars · 2 classes · unmodified WebSocket hibernation not available on Rivet 3 two sockets stay open while the room hibernates, and an edit wakes it Some actor was still awake 60 s after the last client activity 6/7
Source
audreyt/ethercalc at e989429, Worker in packages/worker. Durable Objects: RoomDO, AuthDO using acceptWebSocket, getWebSockets, serializeAttachment, deserializeAttachment, storage.get, storage.put, storage.setAlarm, alarm.
Changes
None. The project ran as published.
Failed steps
  • two sockets stay open while the room hibernates, and an edit wakes it WebSocket hibernation not available on Rivet 3 — WebSocket hibernation is not available on Rivet 3. Orange emulates it: it drops the idle object and keeps its sockets open, but the Rivet actor does not sleep while a socket is open. This step waits for every actor to sleep, so it fails with: Some actor was still awake. Some actor was still awake 60 s after the last client activity With emulated hibernation, this step passes. It still counts as failed.
Works, emulated hibernationhuilang-me/CF-Server-Monitor 2,907 stars · 1 class · unmodified WebSocket hibernation not available on Rivet 3 a browser stays subscribed while the broadcaster hibernates Some actor was still awake 45000ms after the last client activity 6/7
Source
huilang-me/CF-Server-Monitor at 609cc0b, Worker in .. Durable Objects: MetricsBroadcaster using acceptWebSocket, getWebSockets, serializeAttachment, setWebSocketAutoResponse, storage.get, storage.put, storage.setAlarm, alarm.
Changes
None. The project ran as published.
Failed steps
  • a browser stays subscribed while the broadcaster hibernates WebSocket hibernation not available on Rivet 3 — WebSocket hibernation is not available on Rivet 3. Orange emulates it: it drops the idle object and keeps its sockets open, but the Rivet actor does not sleep while a socket is open. This step waits for every actor to sleep, so it fails with: Some actor was still awake. Some actor was still awake 45000ms after the last client activity With emulated hibernation, this step passes. It still counts as failed.
Needs secretssouthleft/figma-console-mcp 2,660 stars · 2 classes · unmodified Needs FIGMA_OAUTH_CLIENT_ID, FIGMA_OAUTH_CLIENT_SECRET 4/5
Source
southleft/figma-console-mcp at 5ef4df3, Worker in .. Durable Objects: FigmaConsoleMCPv3, PluginRelayDO using McpAgent, acceptWebSocket, getWebSockets, storage.get, storage.put, storage.delete.
Changes
None. The project ran as published.
Credentials a real deployment would set
FIGMA_OAUTH_CLIENT_ID, FIGMA_OAUTH_CLIENT_SECRET
Needs secretscloudflare/meet 2,317 stars · 1 class · 2 changes Needs CALLS_APP_ID, CALLS_APP_SECRET 7/8
Source
cloudflare/meet at 314d424, Worker in .. Durable Objects: ChatRoom using storage.get, storage.put, storage.list, storage.delete, storage.deleteAll, setAlarm, getAlarm, alarm.
Changes
  • wrangler.toml: [site] bucket becomes [assets] directory Orange rejects Workers Sites at config load: Unsupported Wrangler configuration: site (repros/workers-sites-unsupported).
  • server.ts: removes the __STATIC_CONTENT_MANIFEST import and the Workers Sites asset handler With no [site], that module does not exist. Static files are served by the assets directory instead.
Credentials a real deployment would set
CALLS_APP_ID, CALLS_APP_SECRET
Works, emulated hibernationcloudflare/templates 2,163 stars · 1 class · unmodified WebSocket hibernation not available on Rivet 3 a socket stays open while the room hibernates, and a message wakes it Some actor was still awake 45000ms after the last client activity 5/6
Source
cloudflare/templates at dc4e76b, Worker in durable-chat-template. Durable Objects: Chat using storage.sql, partyserver.Server, hibernate, broadcast.
Changes
None. The project ran as published.
Failed steps
  • a socket stays open while the room hibernates, and a message wakes it WebSocket hibernation not available on Rivet 3 — WebSocket hibernation is not available on Rivet 3. Orange emulates it: it drops the idle object and keeps its sockets open, but the Rivet actor does not sleep while a socket is open. This step waits for every actor to sleep, so it fails with: Some actor was still awake. Some actor was still awake 45000ms after the last client activity With emulated hibernation, this step passes. It still counts as failed.
Needs secretsakdeb/ElatoAI 2,105 stars · 1 class · unmodified Needs OPENAI_API_KEY, Workers AI 3/4
Source
akdeb/ElatoAI at c0153a2, Worker in server/cloudflare. Durable Objects: ElatoVoiceSession using newUniqueId, WebSocketPair, blockConcurrencyWhile.
Changes
None. The project ran as published.
Credentials a real deployment would set
OPENAI_API_KEY, Workers AI
Needs secretsopenclaw/clawsweeper 2,005 stars · 3 classes · unmodified Needs GITHUB_TOKEN 6/7
Source
openclaw/clawsweeper at 1265122, Worker in dashboard. Durable Objects: StatusStore, ExactReviewQueue, GithubEtagCache using storage.get, storage.put, storage.delete, storage.list, storage.kv, storage.transactionSync, storage.setAlarm, storage.getAlarm, storage.deleteAlarm.
Changes
None. The project ran as published.
Credentials a real deployment would set
GITHUB_TOKEN
Works, emulated hibernationmihaip/infinite-mac 1,652 stars · 1 class · 3 changes WebSocket hibernation not available on Rivet 3 machines stay on the network across the zone's hibernation, and a packet wakes it Some actor was still awake 45000ms after the last client activity 5/6
Source
mihaip/infinite-mac at 7f12363, Worker in .. Durable Objects: EthernetZone using acceptWebSocket, getWebSockets, serializeAttachment, deserializeAttachment.
Changes
  • wrangler.jsonc: removes observability.issues Orange refuses the field at config load: Unknown Wrangler configuration fields: observability.issues (repros/observability-issues-field). It has no effect on the Worker's behaviour.
  • worker/index.ts: removes the SSR import and call for the home page worker/ssr.ts imports src/Data/CD-ROMs.json and *.dsk.json, generated by npm run import-disks with uv, submodules, and native tools that this machine does not have. Unmodified npm run build ends with Build failed with 90 errors: [UNLOADABLE_DEPENDENCY] Could not load src/Data/CD-ROMs.json.
  • build/index.html: adds a one-line page, and the npm run build step is not run The assets directory ./build is the output of the same build, which cannot run here.
Failed steps
  • machines stay on the network across the zone's hibernation, and a packet wakes it WebSocket hibernation not available on Rivet 3 — WebSocket hibernation is not available on Rivet 3. Orange emulates it: it drops the idle object and keeps its sockets open, but the Rivet actor does not sleep while a socket is open. This step waits for every actor to sleep, so it fails with: Some actor was still awake. Some actor was still awake 45000ms after the last client activity With emulated hibernation, this step passes. It still counts as failed.
Needs secretsoiov/vmail 1,498 stars · 1 class · unmodified Needs GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET, GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET 8/9
Source
oiov/vmail at 0213e65, Worker in .. Durable Objects: AccessLedger using getByName, rpc, storage.sql, storage.kv, transactionSync, setAlarm.
Changes
None. The project ran as published.
Credentials a real deployment would set
GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET, GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET
Needs secretsrociiu/talorys 1,435 stars · 1 class · unmodified Needs OPENROUTER_API_KEY 7/8
Source
rociiu/talorys at 420005a, Worker in apps/agent. Durable Objects: TalorysAgent using agents Agent, storage.sql, this.schedule (alarms), onRequest.
Changes
None. The project ran as published.
Credentials a real deployment would set
OPENROUTER_API_KEY
Works, emulated hibernationaozorae/Edgechat 1,395 stars · 6 classes · 1 change WebSocket hibernation not available on Rivet 3 two sockets stay open while the room hibernates, and a message wakes it Some actor was still awake 60 s after the last client activity 6/7
Source
aozorae/Edgechat at 1288c66, Worker in .. Durable Objects: ChannelRoom, UserInbox, Scheduler, InstanceBridge, VoiceCall, TelegramNotifications using acceptWebSocket, getWebSockets, serializeAttachment, deserializeAttachment, storage.setAlarm.
Changes
  • Sets migrations_dir in wrangler.example.toml to a new directory with worker/schema.sql (a symlink) and one admin row The project creates its D1 schema and first admin through GitHub Actions and wrangler d1 execute. The row is what npm run admin:bootstrap generates, with a local-only password.
Failed steps
  • two sockets stay open while the room hibernates, and a message wakes it WebSocket hibernation not available on Rivet 3 — WebSocket hibernation is not available on Rivet 3. Orange emulates it: it drops the idle object and keeps its sockets open, but the Rivet actor does not sleep while a socket is open. This step waits for every actor to sleep, so it fails with: Some actor was still awake. Some actor was still awake 60 s after the last client activity With emulated hibernation, this step passes. It still counts as failed.
PartialThousandBirdsInc/chidori 1,372 stars · 1 class · unmodified The project's own code of many writers racing for one lease, exactly one wins Expected values to be strictly deep-equal: + actual - expected [ 200, + 200, + 200, + 200, + 200, + 200, + 200, 412, - 412, - 412, - 412, - 412, - 412, - 412 ] 6/7
Source
ThousandBirdsInc/chidori at 0a0aba5, Worker in integrations/cloudflare-durable-objects. Durable Objects: ChidoriRun using storage.sql.exec, cursor.toArray, cursor.one.
Changes
None. The project ran as published.
Failed steps
  • of many writers racing for one lease, exactly one wins The project's own code — src/index.ts:172 awaits request.arrayBuffer() between its check and its insert, and workerd does not hold other requests across that await. Measured on wrangler dev and Orange, 10 trials each: 8 winners in every trial, on both. The README claim that writes cannot interleave does not hold on workerd either. Expected values to be strictly deep-equal: + actual - expected [ 200, + 200, + 200, + 200, + 200, + 200, + 200, 412, - 412, - 412, - 412, - 412, - 412, - 412 ]
Partialcloudflare/agents-starter 1,350 stars · 1 class · unmodified WebSocket hibernation not available on Rivet 3 a client stays connected while the agent hibernates, and its next call is answered Some actor was still awake 45000ms after the last client activity 5/7
Source
cloudflare/agents-starter at 4ea6a72, Worker in .. Durable Objects: ChatAgent using storage.sql, storage.setAlarm, acceptWebSocket, getWebSockets, serializeAttachment.
Changes
None. The project ran as published.
Failed steps
  • a client stays connected while the agent hibernates, and its next call is answered WebSocket hibernation not available on Rivet 3 — WebSocket hibernation is not available on Rivet 3. Orange emulates it: it drops the idle object and keeps its sockets open, but the Rivet actor does not sleep while a socket is open. This step waits for every actor to sleep, so it fails with: Some actor was still awake. Some actor was still awake 45000ms after the last client activity With emulated hibernation, this step passes. It still counts as failed.
Credentials a real deployment would set
CLOUDFLARE_API_TOKEN
Works, emulated hibernationcloudflare/partykit 1,306 stars · 1 class · unmodified WebSocket hibernation not available on Rivet 3 editors stay connected across the room's hibernation, and an edit wakes it Some actor was still awake 45000ms after the last client activity 5/6
Source
cloudflare/partykit at f0a2e97, Worker in fixtures/tiptap-yjs. Durable Objects: Document using storage.sql, acceptWebSocket, getWebSockets, serializeAttachment, getByName.
Changes
None. The project ran as published.
Failed steps
  • editors stay connected across the room's hibernation, and an edit wakes it WebSocket hibernation not available on Rivet 3 — WebSocket hibernation is not available on Rivet 3. Orange emulates it: it drops the idle object and keeps its sockets open, but the Rivet actor does not sleep while a socket is open. This step waits for every actor to sleep, so it fails with: Some actor was still awake. Some actor was still awake 45000ms after the last client activity With emulated hibernation, this step passes. It still counts as failed.
Partiali365dev/free4chat 1,225 stars · 1 class · unmodified WebSocket hibernation not available on Rivet 3 a resident Agent's event socket stays open while the Room hibernates, and a message wakes it Some actor was still awake 45000ms after the last client activity 6/8
Source
i365dev/free4chat at 28f7f77, Worker in app. Durable Objects: RoomSession using storage.get, storage.put, setAlarm, alarm, acceptWebSocket, getWebSockets, serializeAttachment.
Changes
None. The project ran as published.
Failed steps
  • a resident Agent's event socket stays open while the Room hibernates, and a message wakes it WebSocket hibernation not available on Rivet 3 — WebSocket hibernation is not available on Rivet 3. Orange emulates it: it drops the idle object and keeps its sockets open, but the Rivet actor does not sleep while a socket is open. This step waits for every actor to sleep, so it fails with: Some actor was still awake. Some actor was still awake 45000ms after the last client activity With emulated hibernation, this step passes. It still counts as failed.
Credentials a real deployment would set
SFU_APP_ID, SFU_APP_SECRET
Workscloudflare/ai 1,212 stars · 1 class · unmodified 5/5
Source
cloudflare/ai at 34a8f4c, Worker in demos/mcp-client. Durable Objects: MyAgent using agents Agent, addMcpServer, storage.sql, WebSocket broadcast.
Changes
None. The project ran as published.
Worksouterbase/starbasedb 1,169 stars · 1 class · unmodified 8/8
Source
outerbase/starbasedb at bb22735, Worker in .. Durable Objects: StarbaseDBDurableObject using storage.sql.exec, storage.setAlarm, storage.getAlarm, alarm, rpc.
Changes
None. The project ran as published.
Works, emulated hibernationshuaiplus/inkstone 1,163 stars · 2 classes · 1 change WebSocket hibernation not available on Rivet 3 a socket stays connected while SyncHub hibernates Some actor was still awake 45000ms after the last client activity 6/7
Source
shuaiplus/inkstone at f59087f, Worker in .. Durable Objects: SyncHub, CredentialVault using acceptWebSocket, getWebSockets, blockConcurrencyWhile, storage.get, storage.put.
Changes
  • Replaces the [exports.SyncHub] and [exports.CredentialVault] tables in wrangler.toml with one migration that creates both SQLite classes. Unmodified, orange dev exits with: Unsupported Wrangler configuration: exports. The build copies that field into dist/inkstone/wrangler.json, the config that npm run deploy uses. The patch shows what lies behind that Orange bug.
Failed steps
  • a socket stays connected while SyncHub hibernates WebSocket hibernation not available on Rivet 3 — WebSocket hibernation is not available on Rivet 3. Orange emulates it: it drops the idle object and keeps its sockets open, but the Rivet actor does not sleep while a socket is open. This step waits for every actor to sleep, so it fails with: Some actor was still awake. Some actor was still awake 45000ms after the last client activity With emulated hibernation, this step passes. It still counts as failed.
Works, emulated hibernationcloudflare/workers-chat-demo 1,123 stars · 2 classes · unmodified WebSocket hibernation not available on Rivet 3 a socket stays open while the room hibernates, and a message wakes it Some actor was still awake 45000ms after the last client activity 4/5
Source
cloudflare/workers-chat-demo at dd32ce8, Worker in .. Durable Objects: ChatRoom, RateLimiter using storage.list, storage.put, acceptWebSocket, serializeAttachment.
Changes
None. The project ran as published.
Failed steps
  • a socket stays open while the room hibernates, and a message wakes it WebSocket hibernation not available on Rivet 3 — WebSocket hibernation is not available on Rivet 3. Orange emulates it: it drops the idle object and keeps its sockets open, but the Rivet actor does not sleep while a socket is open. This step waits for every actor to sleep, so it fails with: Some actor was still awake. Some actor was still awake 45000ms after the last client activity With emulated hibernation, this step passes. It still counts as failed.
Needs secretssupermemoryai/company-brain 1,081 stars · 1 class · unmodified Needs MODEL_API_KEY, SLACK_CLIENT_ID, SLACK_CLIENT_SECRET, SLACK_SIGNING_SECRET, SUPERMEMORY_API_KEY 4/5
Source
supermemoryai/company-brain at ef8a45e, Worker in .. Durable Objects: CompanyBrainAgent using Agent, storage.sql, storage.setAlarm.
Changes
None. The project ran as published.
Credentials a real deployment would set
MODEL_API_KEY, SLACK_CLIENT_ID, SLACK_CLIENT_SECRET, SLACK_SIGNING_SECRET, SUPERMEMORY_API_KEY
Works, emulated hibernationSharzyL/pastebin-worker 1,070 stars · 1 class · unmodified WebSocket hibernation not available on Rivet 3 peers stay connected across the channel's hibernation, and a frame wakes it Some actor was still awake 45000ms after the last client activity 6/7
Source
SharzyL/pastebin-worker at aae764c, Worker in .. Durable Objects: LiveChannel using acceptWebSocket, getWebSockets, setWebSocketAutoResponse.
Changes
None. The project ran as published.
Failed steps
  • peers stay connected across the channel's hibernation, and a frame wakes it WebSocket hibernation not available on Rivet 3 — WebSocket hibernation is not available on Rivet 3. Orange emulates it: it drops the idle object and keeps its sockets open, but the Rivet actor does not sleep while a socket is open. This step waits for every actor to sleep, so it fails with: Some actor was still awake. Some actor was still awake 45000ms after the last client activity With emulated hibernation, this step passes. It still counts as failed.
Works, emulated hibernationsirkirby/unifi-mcp 994 stars · 1 class · unmodified WebSocket hibernation not available on Rivet 3 a relay stays connected while the object hibernates, and a tool call wakes it Some actor was still awake 45000ms after the last client activity 6/7
Source
sirkirby/unifi-mcp at f595762, Worker in apps/worker/worker. Durable Objects: RelayObject using blockConcurrencyWhile, storage.sql.exec, acceptWebSocket, getWebSockets, serializeAttachment, deserializeAttachment.
Changes
None. The project ran as published.
Failed steps
  • a relay stays connected while the object hibernates, and a tool call wakes it WebSocket hibernation not available on Rivet 3 — WebSocket hibernation is not available on Rivet 3. Orange emulates it: it drops the idle object and keeps its sockets open, but the Rivet actor does not sleep while a socket is open. This step waits for every actor to sleep, so it fails with: Some actor was still awake. Some actor was still awake 45000ms after the last client activity With emulated hibernation, this step passes. It still counts as failed.
Needs secretskody-hq/kody 903 stars · 1 class · unmodified Needs CLOUDFLARE_API_TOKEN 6/7
Source
kody-hq/kody at 762a739, Worker in packages/status. Durable Objects: StatusStore using storage.sql.exec, blockConcurrencyWhile, RPC methods, scheduled() into the object.
Changes
None. The project ran as published.
Credentials a real deployment would set
CLOUDFLARE_API_TOKEN
Worksshuaiplus/nodecrypt 897 stars · 1 class · unmodified 6/6
Source
shuaiplus/nodecrypt at 54ed049, Worker in .. Durable Objects: ChatRoom using storage.get, storage.put, storage.delete, WebSocketPair, WebSocket.accept, crypto.subtle.
Changes
None. The project ran as published.
Works, emulated hibernationDhravya/radish 535 stars · 1 class · 2 changes WebSocket hibernation not available on Rivet 3 a connection keeps its name while the object hibernates Some actor was still awake 60 s after the last client activity 7/8
Source
Dhravya/radish at 98768e8, Worker in .. Durable Objects: RedisDO using storage.sql.exec, storage.transactionSync, storage.setAlarm, alarm, acceptWebSocket, getWebSockets, serializeAttachment.
Changes
  • Adds wrangler.jsonc with the REDIS Durable Object and the ColdTier R2 bucket The project configures its Worker only in Alchemy's alchemy.run.ts.
  • Adds src/orange-entry.ts: src/do.ts and src/worker.ts rewritten as a plain Durable Object class and Worker, using the project's Store and SessionExecutor unchanged src/do.ts and src/worker.ts export Alchemy Effect layers. Only Alchemy's bundler turns them into a Worker, and alchemy dev needs a Cloudflare account.
Failed steps
  • a connection keeps its name while the object hibernates WebSocket hibernation not available on Rivet 3 — WebSocket hibernation is not available on Rivet 3. Orange emulates it: it drops the idle object and keeps its sockets open, but the Rivet actor does not sleep while a socket is open. This step waits for every actor to sleep, so it fails with: Some actor was still awake. Some actor was still awake 60 s after the last client activity With emulated hibernation, this step passes. It still counts as failed.
Partialnapolab/y-durableobjects 256 stars · 1 class · unmodified WebSocket hibernation not available on Rivet 3 two open editors keep syncing across a hibernation Some actor was still awake 45000ms after the last client activity 6/7
Source
napolab/y-durableobjects at e6d6d06, Worker in example/apps/workers. Durable Objects: YDurableObjects using acceptWebSocket, getWebSockets, serializeAttachment, storage.get, storage.list, storage.put, storage.delete, storage.transaction, blockConcurrencyWhile.
Changes
None. The project ran as published.
Failed steps
  • two open editors keep syncing across a hibernation WebSocket hibernation not available on Rivet 3 — WebSocket hibernation is not available on Rivet 3. Orange emulates it: it drops the idle object and keeps its sockets open, but the Rivet actor does not sleep while a socket is open. This step waits for every actor to sleep, so it fails with: Some actor was still awake. Under the emulated sleep gate it also fails: the room does not hibernate while the two editors are connected. Some actor was still awake 45000ms after the last client activity With emulated hibernation, this step fails. It still counts as failed.
Works, emulated hibernationtldraw/tldraw-sync-cloudflare 153 stars · 1 class · unmodified WebSocket hibernation not available on Rivet 3 the room hibernates while a connected client pings every 5 s Some actor was still awake 45 s after the last client activity a client stays connected while the room hibernates, and its next push commits Some actor was still awake 45 s after the last client activity 7/9
Source
tldraw/tldraw-sync-cloudflare at 1a4243e, Worker in .. Durable Objects: TldrawDurableObject using acceptWebSocket, getWebSockets, serializeAttachment, deserializeAttachment, setWebSocketAutoResponse, storage.sql.
Changes
None. The project ran as published.
Failed steps
  • the room hibernates while a connected client pings every 5 s WebSocket hibernation not available on Rivet 3 — WebSocket hibernation is not available on Rivet 3. Orange emulates it: it drops the idle object and keeps its sockets open, but the Rivet actor does not sleep while a socket is open. This step waits for every actor to sleep, so it fails with: Some actor was still awake. Some actor was still awake 45 s after the last client activity With emulated hibernation, this step passes. It still counts as failed.
  • a client stays connected while the room hibernates, and its next push commits WebSocket hibernation not available on Rivet 3 — WebSocket hibernation is not available on Rivet 3. Orange emulates it: it drops the idle object and keeps its sockets open, but the Rivet actor does not sleep while a socket is open. This step waits for every actor to sleep, so it fails with: Some actor was still awake. Some actor was still awake 45 s after the last client activity With emulated hibernation, this step passes. It still counts as failed.
Works, emulated hibernationacoyfellow/UserDO 138 stars · 2 classes · unmodified WebSocket hibernation not available on Rivet 3 a socket stays open while the user's object hibernates, and a message wakes it Some actor was still awake 45000ms after the last client activity 5/6
Source
acoyfellow/UserDO at f2a1040, Worker in examples/hono. Durable Objects: MyAppDO, UserDO using storage.get, storage.put, storage.sql, acceptWebSocket, getWebSockets, RPC.
Changes
None. The project ran as published.
Failed steps
  • a socket stays open while the user's object hibernates, and a message wakes it WebSocket hibernation not available on Rivet 3 — WebSocket hibernation is not available on Rivet 3. Orange emulates it: it drops the idle object and keeps its sockets open, but the Rivet actor does not sleep while a socket is open. This step waits for every actor to sleep, so it fails with: Some actor was still awake. Some actor was still awake 45000ms after the last client activity With emulated hibernation, this step passes. It still counts as failed.
Worksbackpine/durable-effect 97 stars · 3 classes · unmodified 7/7
Source
backpine/durable-effect at e93ed10, Worker in examples/effect-worker-api. Durable Objects: CounterDO, OnboardingDO, BillingDO using storage.get, storage.put, storage.delete, setAlarm, getAlarm, deleteAlarm, alarm, rpc.
Changes
None. The project ran as published.
Workslambrospetrou/durable-utils 97 stars · 4 classes · 1 change 7/7
Source
lambrospetrou/durable-utils at 038d378, Worker in test. Durable Objects: TenantDO, RegionPlacerDO, SQLiteDO, CASPaxosDO using storage.sql.exec, storage.kv, storage.transactionSync, RPC, WorkerEntrypoint, RpcTarget.
Changes
  • Adds the README's TenantDO class to the test fixture Worker (test/workers-test.ts), routes that use SQLSchemaMigrations, StaticShardedDO, stubByName, and tryN, and its binding and migration in test/wrangler.toml. library: no deployable Worker in the repository. The fixture Worker and the region-placer example serve only the region placer routes, and do not reach the library's state API.
Worksticket-bridge/hyper-durable 64 stars · 1 class · 1 change 7/7
Source
ticket-bridge/hyper-durable at ad65a62, Worker in consumer. Durable Objects: RubberDuck using storage.get, storage.put, storage.deleteAll, stub.fetch, Proxy returned from the constructor.
Changes
  • Adds consumer/: the README's RubberDuck class, its proxyHyperDurables Worker with routes, and a Wrangler config. library: no deployable Worker in the repository. The test fixture exports only the Counter class, and has no fetch handler.
Worksouterbase/browsable-durable-object 44 stars · 1 class · 1 change 8/8
Source
outerbase/browsable-durable-object at 1299aa4, Worker in consumer. Durable Objects: MyDurableObject using storage.sql.exec, storage.transactionSync, RPC.
Changes
  • Adds consumer/: the README's @Browsable() class and studio() Worker, importing the committed dist/index.js, with a Wrangler config and a tsconfig.json with target es2024. library: no deployable Worker in the repository. The consumer needs its own tsconfig.json because the library's (target ES2020) makes the decorated class throw 'Must call super constructor' when it has a class field, on wrangler dev too.
With emulated hibernation, 25 of the 26 steps that fail for lack of hibernation pass, in 23 projects

Orange emulates hibernation. When an object with open accepted WebSockets is idle, Orange drops the object and keeps its sockets open, and the next message or alarm builds the object again. The Rivet actor stays running the whole time, so the memory and the cost of each connected object remain. This is not Cloudflare's hibernation, where a hibernated object uses no memory and is not billed for duration. An emulated result shows what a step does when the sleep check also accepts this state as asleep. It never changes the status of a step or a claim. A project that fails only hibernation steps, and passes them all this way, shows as works, with emulated hibernation, and is counted apart from the projects that work.

26 of 26 steps reran this way, at OpenOrange ee0b731, 2026-11-10.

11 candidates were left out
  • cloudflare/actors 443 stars Left out on purpose: not useful with Rivet Actors.
  • cloudflare/wildebeest 2,116 stars Its README says it is archived and unmaintained, and its DO config binds no object.
  • supermemoryai/markdowner 2,030 stars No commit since 2024-07-20. package.json lacks a dependency the code imports. Its DO only holds a Browser Rendering session.
  • transitive-bullshit/agentic 18,086 stars Archived.
  • getsentry/sentry-javascript 8,771 stars Its Wrangler configs are test fixtures for the SDK.
  • denoland/celld 6,223 stars A Durable Object runtime, with fixtures. Not an app on Cloudflare.
  • cloudflare/workers-sdk 4,702 stars Wrangler itself. Its Durable Objects are test fixtures.
  • cloudflare/miniflare 3,925 stars A local simulator, archived.
  • rohanprasadofficial/localflare 1,562 stars A local Cloudflare tool, not an app.
  • secondsky/claude-skills 244 stars Skill templates, not a deployed project.
  • syumai/workers-go 1,181 stars A Go library. Its Durable Objects are examples.

On Rivet Cloud.

Six projects also ran on Rivet Cloud, one run each on a Free cluster. These results are separate from the local ones above.

Worksstarbasedbouterbase/starbasedborange deploy · Free cluster · 2026-11-05A SQL database over HTTP and WebSocket, built on a Durable Object's SQLite. 7/7 pass 1 not applicable
What ran
The API refused a request with no token. A client created a table, inserted rows, ran a transaction, used the REST API and JSON export, and queried over a WebSocket. The table survived an idle wait and a real rollout.
Where it falls short
  • The cron callback step did not apply: it calls a local server, which a pool can't reach.
  • The recorded run is the third attempt. The first was stopped because the old build might still have been serving. The second failed on rows the first had left and on a wrong sleep check in the test runner.
  • The API needs a token, and there is no page to open in a browser.
Steps
  • a request without a token gets 401 Pass
  • a client creates a table, inserts rows, and reads them back Pass
  • the README's $1 query and transaction return their rows Pass
  • the REST API writes a row, and the JSON export sees it Pass
  • a WebSocket client queries the same database Pass
  • a cron task's alarm calls the task's callback host The callback host is a local HTTP server, which a pool cannot reach Not applicable
  • the table survives the object's sleep Waited 30 s idle with no socket open. Sleep itself is not proven on a pool. Pass
  • the table survives an orange dev and engine restart Pass
Source
outerbase/starbasedb at bb22735.
Workstldrawtldraw/tldrawrivet deploy · Free cluster · 2026-11-05The sync backend of tldraw's multiplayer whiteboard, with one Durable Object per room and assets in R2. 6/6 pass
What ran
Assets uploaded to and read from R2 on a Google Cloud Storage bucket, through Orange's S3 settings. Two clients synced pages over WebSockets, a late joiner got them, and a page survived the room emptying and a real rollout.
Where it falls short
  • This is the backend only, with no editor to open.
  • The image needed the Worker bundled by hand first, because the Orange it ran on could not install workspace: packages inside the image.
  • Only the object reads and writes the project uses ran against Cloud Storage.
Steps
  • an uploaded asset is stored once in R2 and comes back Pass
  • a page pushed by one client reaches the other client in the room Pass
  • a client that joins while the room is live gets the page in its hydration Pass
  • a connected client keeps the room alive through an idle period, and its next push commits Pass
  • when everyone leaves the room saves to R2 and sleeps, and the page comes back from R2 Waited about 16 s after the sockets closed, past the 10 s sleep timeout. Sleep itself is not proven on a pool. Pass
  • a page pushed before an orange dev and engine restart is there after it Pass
Source
tldraw/tldraw at aae1c5d, in apps/bemo-worker.
Workscomputercloudflare/computerrivet deploy · Free cluster · 2026-11-05A workspace in a Durable Object, with a filesystem and a shell that runs in a Dynamic Worker. This was the first Dynamic Worker on a cluster. 6/6 pass
What ran
Files written through the object read back, each workspace stayed separate, and a shell in a Dynamic Worker read and wrote the same files. A bundled skill mounted read-only. Files survived an idle wait and a real rollout.
Where it falls short
  • The image needed the Worker bundled by hand first, because the project's package comes from its monorepo.
  • The scenario does not touch the R2 mount. A separate check read and listed a Cloud Storage object through it. The project's mount is read-only.
Steps
  • the Worker lists its routes, and refuses paths outside the workspace Pass
  • a file written through the Durable Object reads back, and each workspace is separate Pass
  • a shell in a Dynamic Worker reads and writes the Durable Object's filesystem Pass
  • the skill bundled with the Worker is mounted read-only Pass
  • files survive the Durable Object's sleep, and the shell still runs Waited 30 s idle with no socket open. Sleep itself is not proven on a pool. Pass
  • files survive a restart, and the shell still runs Pass
Source
cloudflare/computer at b995d86, in examples/worker-shell.
Workskodykody-hq/kodyrivet deploy · Free cluster · 2026-11-05A status page for the Kody app, where a one-minute cron probes components and a Durable Object stores incidents. 4/4 pass 2 not applicable1 needs secrets
What ran
The page and its JSON read from the store. The real cron fired on the pool, and three failing passes opened an incident, which survived an idle wait and a real rollout.
Where it falls short
  • Its origin points at a host that never answers, so the pool doesn't probe the project's real site. So every component reads down, and that outage comes from this setup.
  • Two steps did not apply, because they need an origin that answers or recovers.
  • Operator alert email needs a real credential.
  • A binding to the project's jobs Worker points at a Worker that isn't deployed. No step called it.
Steps
  • the status page and its JSON read from the store Pass
  • the one-minute cron runs a probe pass into the object It asserts a healthy origin. The local scenario serves one on 127.0.0.1, which a pool can't reach, so the origin here is a host that never answers Not applicable
  • three failing passes open an incident, and the page shows it Pass
  • the open incident survives the object's sleep Waited 30 s idle with no socket open, and the cron wakes this object each minute. Sleep itself is not proven on a pool. Pass
  • the open incident survives a restart Pass
  • after the restart, the cron runs again, and two good passes resolve the incident It needs an origin that recovers, which a pool can't reach Not applicable
  • an operator alert email goes out through the Cloudflare Email API Needs CLOUDFLARE_API_TOKEN Needs secrets
Source
kody-hq/kody at 762a739, in packages/status.
Partialpartykitcloudflare/partykitrivet deploy · Free cluster · 2026-11-05A collaborative text editor fixture on PartyServer, with Yjs documents in Durable Objects. 5/6 pass
What ran
Two editors synced edits both ways over WebSockets, and a custom message reached the others. A document was saved when its room emptied, came back after an idle wait, stayed separate from another room's, and survived a real rollout.
Where it falls short
  • Editors staying connected across a room's hibernation failed, as expected: WebSocket hibernation is not available on Rivet 3, so open sockets keep the object awake.
  • The editor client isn't in the deployed assets, so there is nothing to open in a browser.
Steps
  • editors stay connected across the room's hibernation, and an edit wakes it A client socket stayed open or a request ran within the idle window for 90000ms, so the object could not sleep Fail
  • two editors sync edits in both directions Waited 30 s idle with no socket open. Sleep itself is not proven on a pool. Pass
  • a custom ping answers the sender and notifies the others Pass
  • the document is saved when the room empties, and comes back after a sleep Waited 30 s idle with no socket open. Sleep itself is not proven on a pool. Pass
  • a room's document is separate from another room's Pass
  • the document survives an orange dev and engine restart Pass
Source
cloudflare/partykit at f0a2e97, in fixtures/tiptap-yjs.
Workssupermemorysupermemoryai/supermemoryrivet deploy · Free cluster · 2026-11-05Supermemory's MCP server, which gives AI clients a memory, with a Durable Object for each user's active space and for upload sessions. 4/4 pass
What ran
The server described itself and its OAuth metadata, refused a client with no token, and refused an unknown upload token. With a real Supermemory sign-in, a token was accepted on the pool, an upload session worked once and refused a second use, and the active space carried across connections.
Where it falls short
  • Uploads don't work for a real client on a pool URL. The Worker builds its upload URL from MCP_RESOURCE, which stays on Supermemory's production host so that tokens match, so a client following it gets a 401 from production. The passing step posted the same path to the pool by hand.
  • The image needed build.command removed after running it by hand, because the Orange it ran on refused a custom build.
  • The sign-in step ran by a separate script, after two attempts stopped on that script's own checks.
Steps
  • serves the server description and the OAuth resource metadata Pass
  • an MCP client without a token gets 401 with the resource metadata Pass
  • SpaceState refuses an upload token with no session Pass
  • the active space is stored in SpaceState and an upload session is consumed once Ran once with a real Supermemory sign-in, by a separate script through the project's public MCP API. The upload went to the pool by hand, because the Worker advertises Supermemory's production host for uploads. Pass
Source
supermemoryai/supermemory at 16ed414, in apps/mcp.
How these runs were set up
  • Each scenario ran on one shared Free cluster, recorded as Engine 3.0.0 when it was created, the day before these runs. That version comes from the creation record, and was not read during the runs. Each project then got its own Free cluster, where one real request proved it. Those clusters report Engine 3.0.0.
  • Only starbasedb used orange deploy's upload and rollout. The others used the image orange deploy --dry-run writes, uploaded and rolled out with the Rivet CLI.
  • Sleep isn't proven on a pool. The Engine API's actor timestamps are null, and these images log no lifecycle lines, so sleep steps wait past the idle window and read state afterward. A restart step is a real rollout to a newly built image.
  • A deploy reports done before the new build serves, so each scenario waited for the old node to leave and a project-specific request to succeed.
  • The Orange under test was a local merge of the CLI and Durable Object branches, before they landed.

Cloudflare's templates.

26 templates from Cloudflare, each run on OpenOrange beside wrangler dev 4.129.0 in three modes. Recorded by hand at OpenOrange c921bf3, 2026-10-21; "was" is the run at 6af8602, 2026-10-20.

Config unchanged
10work · was 9 15start · was 15
The Wrangler config as published, plus d1 migrations apply.
+ build step
15work · was 11 21start · was 21
Also runs the project’s own build, or puts node_modules/.bin on PATH.
+ probe config
17work · was 13 25start · was 25
Also adds one config key, such as assets.directory for Vite-plugin projects.
Works.
Every tested flow behaves as it does on wrangler dev.
Partial.
Starts; some flows break.
Fails.
Does not run.
Needs a step.
Needs a step this mode skips, so it does not start.
Config unchangedWorkshello-world-do-template+ build stepWorks+ probe configWorks3/3
Flows tested
/, /any/path
What still blocks
Nothing. Every mode works.
Source
cloudflare/templates
Config unchangedWorksd1-template+ build stepWorks+ probe configWorks3/3
Flows tested
GET / comments
What still blocks
Nothing. Every mode works.
Source
cloudflare/templates
Config unchangedPartialchanfana-openapi-template+ build stepPartial+ probe configPartial0/3
Flows tested
/openapi.json, task POST, GET, DELETE
What still blocks
DELETE … LIMIT fails: Orange's SQLite is built without SQLITE_ENABLE_UPDATE_DELETE_LIMIT.
Source
cloudflare/templates
Config unchangedWorksopenauth-template+ build stepWorks+ probe configWorks3/3
Flows tested
/ redirect, /authorize
What still blocks
Nothing. Every mode works.
Source
cloudflare/templates
Config unchangedWorksnodejs-http-server-template+ build stepWorks+ probe configWorks3/3
Flows tested
/, /api/status
What still blocks
Nothing. Every mode works.
Source
cloudflare/templates
Config unchangedNeeds a stepdurable-chat-template+ build stepWorks+ probe configWorks2/3
Flows tested
assets, WebSocket chat, history, idle then broadcast
What still blocks
Config unchanged: the esbuild build command needs node_modules/.bin on PATH. Wrangler is the same.
Source
cloudflare/templates
Config unchangedWorkswas Partialmultiplayer-globe-template+ build stepWorkswas Partial+ probe configWorkswas Partial3/3
Flows tested
2 WebSocket clients, markers
What still blocks
Nothing. Every mode works.
Source
cloudflare/templates
Config unchangedPartialllm-chat-app-template+ build stepPartial+ probe configPartial0/3
Flows tested
POST /api/chat
What still blocks
Needs an AI key, and @cf/meta/llama-3.1-8b-instruct-fp8 needs an ORANGE_AI_MODELS mapping.
Source
cloudflare/templates
Config unchangedNeeds a stepworkflows-starter-template+ build stepWorkswas Partial+ probe configWorkswas Partial2/3
Flows tested
start, waiting, event, complete, DO WebSocket
What still blocks
Config unchanged: the build creates assets.directory. Wrangler is the same.
Source
cloudflare/templates
Config unchangedNeeds a stepto-do-list-kv-template+ build stepWorks+ probe configWorks2/3
Flows tested
SSR redirect, create and list todos (KV)
What still blocks
Config unchanged: needs npm run build first. Wrangler is the same.
Source
cloudflare/templates
Config unchangedNeeds a stepagents tictactoe+ build stepNeeds a step+ probe configWorks1/3
Flows tested
Agent WebSocket, makeMove updates state
What still blocks
The Vite-plugin config has no assets.directory until the probe adds it. Wrangler is the same.
Source
cloudflare/templates
Config unchangedFailsagents mcp+ build stepFails+ probe configFails0/3
Flows tested
start
What still blocks
The .svg import is Vite-only, and the Vite build output uses no_bundle, which Orange rejects.
Source
cloudflare/templates
Config unchangedNeeds a stepagents mcp-worker+ build stepNeeds a step+ probe configWorks1/3
Flows tested
MCP initialize, tools/list, tools/call
What still blocks
The Vite-plugin config needs the assets.directory probe.
Source
cloudflare/templates
Config unchangedNeeds a stepagents ai-chat+ build stepNeeds a step+ probe configPartial0/3
Flows tested
Agent WebSocket, chat turn
What still blocks
Chat turns need ORANGE_AI_API_KEY or OPENROUTER_API_KEY. The Vite-plugin config needs the probe.
Source
cloudflare/templates
Config unchangedNeeds a stepagents resumable-stream-chat+ build stepNeeds a step+ probe configPartial0/3
Flows tested
Agent WebSocket, chat turn
What still blocks
The chat stream needs an AI key. The Vite-plugin config needs the probe.
Source
cloudflare/templates
Config unchangedPartialagents playground+ build stepPartial+ probe configPartial0/3
Flows tested
state, callable, and schedule agents, restart
What still blocks
/ is 404: the Vite SPA does not build outside the agents monorepo.
Source
cloudflare/templates
Config unchangedWorksnodejs-als-app+ build stepWorks+ probe configWorks3/3
Flows tested
/
What still blocks
Nothing. Every mode works.
Source
cloudflare/templates
Config unchangedPartialnodejs-hybrid-app+ build stepPartial+ probe configPartial0/3
Flows tested
crypto, sqlite, http, process-env, require-alias
What still blocks
No such module "cross-fetch": Wrangler's unenv npm aliases are not ported.
Source
cloudflare/templates
Config unchangedWorksunbound-durable-object+ build stepWorks+ probe configWorks3/3
Flows tested
ctx.exports DO, persistence across restart
What still blocks
Nothing. Every mode works.
Source
cloudflare/templates
Config unchangedWorkscloudflare/workers-chat-demo+ build stepWorks+ probe configWorks3/3
Flows tested
join, post, leave, idle, rejoin
What still blocks
Nothing. Every mode works.
Source
cloudflare/templates
Config unchangedPartialouterbase/starbasedb+ build stepPartial+ probe configPartial0/3
Flows tested
bin/sbtest.sh
What still blocks
/export/dump is not authorized: Rivet's _rivet_ tables show in sqlite_master, and reading them is denied.
Source
cloudflare/templates
Config unchangedNeeds a steptldraw/tldraw-sync-cloudflare+ build stepWorkswas Partial+ probe configWorkswas Partial2/3
Flows tested
/, unfurl, sync, R2 upload and download
What still blocks
Config unchanged: needs vite build first. Wrangler is the same.
Source
cloudflare/templates
Config unchangedNeeds a stepthreepointone/durable-chat+ build stepPartial+ probe configPartial0/3
Flows tested
WebSocket chat, history, hibernation
What still blocks
AI replies need an AI key, and @cf/meta/llama-2-7b-chat-int8 has no default model mapping.
Source
cloudflare/templates
Config unchangedWorksSpl0itable/nosflare+ build stepWorks+ probe configWorks3/3
Flows tested
NIP-42 AUTH, REQ/EOSE, EVENT, cron
What still blocks
Nothing. Every mode works.
Source
cloudflare/templates
Config unchangedNeeds a stepkiyo-e/pairlane+ build stepWorkswas Partial+ probe configWorkswas Partial2/3
Flows tested
create rooms (Rate Limiting), WebSocket signaling
What still blocks
Config unchanged: needs npm run build first. Wrangler is the same.
Source
cloudflare/templates
Config unchangedWorksnapolab/y-durableobjects+ build stepWorks+ probe configWorks3/3
Flows tested
Yjs RPC and WebSocket sync
What still blocks
Nothing. Every mode works.
Source
cloudflare/templates

Durable Objects, test by test.

87 of 99 Durable Object tests pass: 19 of 22 from workerd's suite, and 68 of 77 that OpenOrange ports from workerd's C++ tests, scored only where workerd passes them.

OpenOrange's own tests

  • Passes
  • Fails, a known gap in the matrix
  • Fails
  • do-alarm-test 17/17
  • do-id-test 2/2
  • do-input-gate-test 5/5
  • do-sql-test 7/15
  • do-storage-test 24/24
  • do-websocket-hibernation-test 2/3
  • do-websocket-test 11/11

Still failing

12 of 99, upstream and OpenOrange's own. A Known gap is a difference the feature matrix records; its row says why. Open a row for the error.

Known gapdurableObjectTestnew-module-registry-do-testBehavior differsOff. The table says false. Orange always bundles the Worker with esbuild, and setting the flag only prints the ignored-flag warning.new_module_registry
Test
api-tests--new-module-registry-do-test › durableObjectTest
Error
AssertionError: Expected values to be strictly equal: | + actual - expected |
Failsqueue-do-uaf-testqueue-do-uaf-testBehavior differs—
Test
api-tests--queue-do-uaf-test › queue-do-uaf-test
Error
TypeError: The receiving Durable Object does not support RPC, because its class was not declared with `extends DurableObject`. In order to enable RPC, make sure your class extends the special class `D
Known gapmainsql-testBehavior differsSame, through RivetKit SQLite 3.46.0. Errors end with the SQLite result code, for example no such table: x: SQLITE_ERROR.ctx.storage.sql.exec()
Test
api-tests--sql-test › main
Error
Error: no such function: cos at offset 7: SQLITE_ERROR
Known gapauthorizerDefaultExpressionsdo-sql-testBehavior differsNo authorizer runs. Blocked functions in DEFAULT expressions run.Authorizer in DEFAULT expressions
Test
synthetic--do-sql-test › authorizerDefaultExpressions
Error
AssertionError: Missing expected exception.
Known gapdeleteWithLimitdo-sql-testBehavior differsFails with near "LIMIT": syntax error: SQLITE_ERROR. RivetKit's SQLite build lacks the grammar rule.DELETE and UPDATE with LIMIT
Test
synthetic--do-sql-test › deleteWithLimit
Error
Error: near "LIMIT": syntax error at offset 19: SQLITE_ERROR
Known gapinternalFunctionsBlockeddo-sql-testBehavior differsNo allow-list. Internal functions run.SQL function allow-list
Test
synthetic--do-sql-test › internalFunctionsBlocked
Error
AssertionError: Missing expected exception.
Known gaplargeRowCountersdo-sql-testBehavior differsThe number of rows returned.cursor.rowsRead
Test
synthetic--do-sql-test › largeRowCounters
Error
AssertionError: 0 == 1
Known gapreadRowCountersdo-sql-testBehavior differsThe number of rows returned.cursor.rowsRead
Test
synthetic--do-sql-test › readRowCounters
Error
AssertionError: 0 == 1
Known gapregulatorReservedNamesdo-sql-testBehavior differsA text check blocks _cf_ and _rivet_ names with not authorized.Reserved _cf_ table names
Test
synthetic--do-sql-test › regulatorReservedNames
Error
AssertionError: The input did not match the regular expression /access to _cf_KV\.key is prohibited/. Input: | | 'Error: not authorized'
Known gaptriggerRowCountersdo-sql-testBehavior differssqlite3_changes() for statements that start with INSERT, UPDATE, DELETE, or REPLACE. 0 otherwise.cursor.rowsWritten
Test
synthetic--do-sql-test › triggerRowCounters
Error
AssertionError: 1 == 2
Known gapwriteRowCountersdo-sql-testBehavior differssqlite3_changes() for statements that start with INSERT, UPDATE, DELETE, or REPLACE. 0 otherwise.cursor.rowsWritten
Test
synthetic--do-sql-test › writeRowCounters
Error
AssertionError: Expected values to be loosely deep-equal: | | {
Known gapcloseWhileHibernatedKeepsCodeAndReasondo-websocket-hibernation-testBehavior differsCalls webSocketClose(ws, code, reason, wasClean) once. The socket stays listed until the handler settles.Durable Object webSocketClose()
Test
synthetic--do-websocket-hibernation-test › closeWhileHibernatedKeepsCodeAndReason
Error
AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal: | + actual - expected |

How the score moved.

34 saved runs, one point per commit, from Orange PR #2 base (Orange PR #1 head) (e1aec90) to this one. Every counted test, upstream and OpenOrange's own. Hover the chart for a run's counts.

  • Pass 1,670
  • Ran with /tmp remapped, not scored 0
  • Behavior differs 112
  • Not supported 50
  • Timeout 11
  • Error 8
0%
20%
40%
60%
80%
100%
e1aec90 Sep 6, 23:44 ea40348 Nov 10, 20:08

Counts in the legend are this run's. Runs are evenly spaced in commit order. Times are UTC: the commit time, or the run's start where the commit time was not recorded. The total moves when the suite or what is counted changes; each run's note below says why.

Since the previous run

Compared test by test with #10 at ee0b731 on RivetKit 3.0.6, with #11 and #7 (ee0b731, 2026-11-10): 1,679 of 1,860 then, 1,670 of 1,851 now.

Newly passing0

None.

Newly failing0

None.

No longer counted9

  • 9 only check a Cloudflare quota OpenOrange does not enforce, and were cut from the score. See the list.

By area, since the first run

workerd's suite only. 1,602 of 1,774 pass, +216 since Stock Node.js for node: imports, the first run that counted tests the way this one does. Each area compares with its own first comparable run.

  • Passed on the first run
  • Passes since
  • Fails
  • Node.js compat +159 since 6b50c33 758/771 · 98.3%
  • Web platform +238 since e1aec90 307/427 · 71.9%
  • Streams +184 since e1aec90 247/254 · 97.2%
  • RPC + entrypoints +153 since e1aec90 154/179 · 86%
  • Fetch, HTTP, sockets +73 since e1aec90 103/107 · 96.3%
  • Durable Objects +13 since e1aec90 19/22 · 86.4%
  • Crypto +6 since e1aec90 14/14 · 100%

Every run

37 runs of workerd's suite, newest first, including 3 early ones recorded by hand. Open a run for its note.

Latest#10 at 028a0da with #11 and #7: Cloudflare quotas removed, quota-only tests cutea40348 · 2026-11-100.0.0-sqlite-sync-3-0-6-final.cf8679c 1,602 · 90.3%
Note
Limits revisions on #10 (Rivet limits only), with 9 quota-only workerd tests cut from the score.
Counted
1,602 of 1,774 workerd tests pass.
#10 at ee0b731 on RivetKit 3.0.6, with #11 and #7ee0b731 · 2026-11-100.0.0-sqlite-sync-3-0-6-final.cf8679c 1,611 · 90.4%
Note
Cascade 7 tip: deploy variables and secrets in #9, WebSocket hibernation emulation in #10, then #11 and #7.
Counted
1,611 of 1,783 workerd tests pass.
#10 at 9d24f50 on RivetKit 3.0.6, with #11 and #79d24f50 · 2026-11-090.0.0-sqlite-sync-3-0-6-final.cf8679c 1,611 · 90.4%
Note
Cascade 5 tip: #8 re-pinned to 0.0.0-sqlite-sync-3-0-6-final.cf8679c, then #9, #10, #11, and #7.
Counted
1,611 of 1,783 workerd tests pass.
#10 at 62e4783 with #11 and #762e4783 · 2026-11-070.0.0-sqlite-sync-3-0-1-final.5663d2f 1,611 · 90.4%
Note
Cascade 4 tip: #9 zpsykowm, #10 with the kody fixes (multi-Worker serve, Vectorize, config and runtime fixes), #11, and #7.
Counted
1,611 of 1,783 workerd tests pass.
#10 at 09b4d1d with #11 and #709b4d1d · 2026-11-060.0.0-sqlite-sync-3-0-1-final.5663d2f 1,607 · 90.3%
Note
Cascade 3 tip: #9 zpsykowm, #10 with the node:http, email, and Browser Rendering revisions, #11 with the do-rpc claim, and #7.
Counted
1,607 of 1,779 workerd tests pass.
#10 at 66696ab with #11 and #766696ab · 2026-11-060.0.0-sqlite-sync-3-0-1-final.5663d2f 1,609 · 90.2%
Note
Cascade tip: #9 zpsykowm, #10 with the stub order, schema listing, and module import fixes, #11, and #7.
Counted
1,609 of 1,783 workerd tests pass.
Show 31 earlier runs
#10 at 6feb94b with #11 and #76feb94b · 2026-11-050.0.0-sqlite-sync-3-0-1-final.5663d2f 1,609 · 90.2%
Note
Cascade tip: #9 ywmtylvu, #10 with the stub order fix, #11, and #7.
Counted
1,609 of 1,783 workerd tests pass.
PR #10 at 4208c604208c60 · 2026-11-050.0.0-sqlite-sync-3-0-1-final.5663d2f 1,608 · 90.2%
Note
Orange 4208c60 with the DO fixes, on RivetKit 5663d2f.
Counted
1,608 of 1,783 workerd tests pass.
PR #10 at 96efb7b96efb7b · 2026-11-050.0.0-sqlite-sync-3-0-1-final.5663d2f 1,609 · 90.2%
Note
Orange 96efb7b with the DO fixes, on RivetKit 5663d2f.
Counted
1,609 of 1,783 workerd tests pass.
PR #10 at 80d632880d6328 · 2026-11-050.0.0-sqlite-sync-3-0-1-final.5663d2f 1,609 · 90.2%
Note
Orange 80d6328 with the DO fixes, on RivetKit 5663d2f.
Counted
1,609 of 1,783 workerd tests pass.
PR #10 at cb1ffb0cb1ffb0 · 2026-11-050.0.0-sqlite-sync-3-0-1-final.5663d2f 1,609 · 90.2%
Note
Orange cb1ffb0 with the DO fixes, on RivetKit 5663d2f.
Counted
1,609 of 1,783 workerd tests pass.
PR #10 at e4c405fe4c405f · 2026-11-050.0.0-sqlite-sync-3-0-1-final.5663d2f 1,606 · 90.1%
Note
Orange e4c405f with the DO fixes, on RivetKit 5663d2f.
Counted
1,606 of 1,783 workerd tests pass.
PR #10 at a060c26a060c26 · 2026-11-050.0.0-sqlite-sync-3-0-1-final.5663d2f 1,605 · 90%
Note
Orange a060c26 with the DO fixes, on RivetKit 5663d2f.
Counted
1,605 of 1,783 workerd tests pass.
PR #10 at 1d97c8ff1d97c8f · 2026-11-040.0.0-sqlite-sync-3-0-1-final.5663d2f 1,590 · 89.2%
Note
Orange 1d97c8ff with the DO fixes and the open-socket workaround, on RivetKit 5663d2f.
Counted
1,590 of 1,783 workerd tests pass.
PR #8 on RivetKit 3.0.1814001d · 2026-11-040.0.0-sqlite-sync-3-0-1-final.5663d2f 1,590 · 89.2%
Note
Orange 814001d with the sync SQLite preview on v3.0.1 (5663d2f).
Counted
1,590 of 1,783 workerd tests pass.
Tail Workers + req.socket + /tmp quirks removedac85bc6 · 2026-10-310.0.0-sqlite-sync-3x-release.a00b07f 1,590 · 89.2%
Note
Adds tail_consumers, a facet string id, req.socket address fields, and removes the two /tmp workerd quirks.
Counted
1,590 of 1,783 workerd tests pass.
v3gate238b6161 · 2026-10-290.0.0-sqlite-sync-3x-release.a00b07f 1,581 · 88.7%
Counted
1,581 of 1,783 workerd tests pass.
RivetKit 3 + sync SQLite, v3 only 2026-10-29161e250 · 2026-10-290.0.0-feat-sqlite-sync-3x.a00b07f 1,426 · 80%
Counted
1,426 of 1,783 workerd tests pass. 154 of them ran with /tmp remapped and count as neither pass nor fail; 153 of those pass.
Workflows port + facets clone + edge fixese939c3b · 2026-10-240.0.0-feat-sqlite-sync.a2b9069 1,426 · 80%
Counted
1,426 of 1,783 workerd tests pass. 154 of them ran with /tmp remapped and count as neither pass nor fail; 153 of those pass.
DO stub errors + RPC types6b1d4f6 · 2026-10-240.0.0-feat-sqlite-sync.a2b9069 1,427 · 80%
Counted
1,427 of 1,783 workerd tests pass. 154 of them ran with /tmp remapped and count as neither pass nor fail; 153 of those pass.
Conformance fixes: Worker Loader, RPC, SubtleCrypto, ctx.abort()ee51c45 · 2026-10-230.0.0-feat-sqlite-sync.a2b9069 1,426 · 80%
Counted
1,426 of 1,783 workerd tests pass. 154 of them ran with /tmp remapped and count as neither pass nor fail; 153 of those pass.
Bindings cleanup, serve and deploy fixes, conformance gate58f3e73 · 2026-10-230.0.0-feat-sqlite-sync.a2b9069 1,386 · 77.7%
Counted
1,386 of 1,783 workerd tests pass. 154 of them ran with /tmp remapped and count as neither pass nor fail; 153 of those pass.
Stack rebased on the CLIafe3ba7 · 2026-10-200.0.0-feat-sqlite-sync.a2b9069 1,385 · 77.7%
Counted
1,385 of 1,783 workerd tests pass. 154 of them ran with /tmp remapped and count as neither pass nor fail; 153 of those pass.
Real backends for bindings, multi-Worker, sandboxes2c3c4c0 · 2026-10-200.0.0-feat-sqlite-sync.a2b9069 1,386 · 77.7%
Counted
1,386 of 1,783 workerd tests pass. 154 of them ran with /tmp remapped and count as neither pass nor fail; 153 of those pass.
Stock Node.js, fs tests with /tmp remappedfb6ea99 · 2026-10-200.0.0-feat-sqlite-sync.a2b9069 1,386 · 77.7%
Counted
1,386 of 1,783 workerd tests pass. 154 of them ran with /tmp remapped and count as neither pass nor fail; 153 of those pass.
Stock Node.js for node: imports6b50c33 · 2026-10-200.0.0-feat-sqlite-sync.a2b9069 1,386 · 73.4%
Note
Run on 2e1179f, which has the same content as 6b50c33 apart from file modes.
Counted
1,386 of 1,888 workerd tests pass.
Orange PR #2: Durable Object fetch heads, no_bundle, restart fix4ec8d56 · 2026-10-200.0.0-feat-sqlite-sync.a2b9069 1,862 · 85.3%
Counted
1,862 of 2,182 workerd tests pass.
Orange PR #2: assets, D1 migrations, WebSocket and small fixes9b0fdb1 · 2026-10-200.0.0-feat-sqlite-sync.a2b9069 1,863 · 85.4%
Counted
1,863 of 2,182 workerd tests pass.
Orange PR #2: Wrangler build fixescaa4bb7 · 2026-10-190.0.0-feat-sqlite-sync.32022a9 1,863 · 85.4%
Note
Run on 896d16d, which has the same tree as caa4bb7.
Counted
1,863 of 2,182 workerd tests pass.
Orange PR #2: 85% push1d75c46 · 2026-10-190.0.0-feat-sqlite-sync.32022a9 1,857 · 85.1%
Counted
1,857 of 2,182 workerd tests pass.
Orange PR #2 conformance push9e5e48b · 2026-10-190.0.0-feat-sqlite-sync.18dce02 1,826 · 83.7%
Counted
1,826 of 2,182 workerd tests pass.
Orange PR #2 + DO fixes669cad5 · 2026-10-180.0.0-feat-sqlite-sync.18dce02 1,637 · 75.6%
Note
Ran on the working tree that became commit 669cad5.
Counted
1,637 of 2,164 workerd tests pass.
Orange PR #2b170fbd · 2026-10-180.0.0-feat-sqlite-sync.18dce02 1,636 · 75.6%
Note
Before the synthetic Durable Object tests. Commit b170fbd was made 34 s before the run started, but the tree was not checked against it.
Counted
1,636 of 2,164 workerd tests pass.
By handFixes + DO fixesno commit · 2026-10-17— 1,616 · 74.5%
Note
Final rivet stack 9177a822 with a linked release build. Recorded from the run's aggregate before saved results existed.
Counted
1,616 of 2,168 workerd tests pass, as recorded by hand.
By handFixes to Orange PR #1no commit · 2026-10-16— 1,611 · 74.3%
Note
Earlier rivet stack with a debug NAPI build. Only totals were recorded.
Counted
1,611 of 2,168 workerd tests pass, as recorded by hand.
By handOrange PR #1e1aec90 · 2026-10-16— 744 · 34.2%
Note
RivetKit preview build from rivet PR #5659. Recorded from the run's aggregate before saved results existed.
Counted
744 of 2,174 workerd tests pass, as recorded by hand.
Orange PR #2 base (Orange PR #1 head)e1aec90 · 2026-10-200.0.0-sync-sqlite.0ed739a 684 · 31.3%
Note
Run with the upstream runner from 3ca6350, because the runner did not exist at e1aec90. Orange runtime and RivetKit are from e1aec90.
Counted
684 of 2,182 workerd tests pass.

Feature matrix.

624 items: every binding, handler, API, module, flag, config key and limit. A red dot is a cited test that fails in the latest run.

Supported.
OpenOrange implements the Cloudflare API.
Alternative.
The same API, on an OpenOrange backend such as Rivet Actors.
Partial.
Works with a known difference. The row says which.
Stub.
The binding loads; every call throws an error that names it.
Rejected.
Fails at config load or Worker load with a clear error.
Unsupported.
Missing, ignored, or wrong without a clear error.
N/A.
Deploy-only, workerd-only, or experimental. Not scored.

Bindings

Supportedvars (string values)Each string in vars appears on env as a string.Wrangler converts each string var to a plain_text binding, and Orange puts the string on env. 4 files
Notes
Named environments follow Wrangler's rules, because Orange reads the config with Wrangler's unstable_readConfig.
Source
src/config/load-wrangler.ts:787-792packages/runtime-node/src/runner.ts:471-473src/runtime/bindings.test.ts:138-148src/config/load-wrangler.test.ts:13-32
Supportedvars (JSON values)Each non-string value in vars appears on env as a parsed JSON value.Wrangler converts each non-string var to a json binding, and Orange puts the value on env. 3 files
Notes
A .dev.vars or .env key with the same name replaces the JSON value with a string.
Source
src/config/load-wrangler.ts:793-794packages/runtime-node/src/runner.ts:471-473src/runtime/bindings.test.ts:138-148
Supported.dev.vars secretswrangler dev loads keys from .dev.vars (or .dev.vars.<env>) into env as secret text.Orange calls Wrangler's unstable_getVarsForDev, so .dev.vars keys reach env as strings, like wrangler dev. 3 files
Notes
A .dev.vars key replaces a var with the same name. It does not replace a binding of another type, such as a Secrets Store secret. When the config has secrets.required, only listed keys and keys that are also vars load, and a missing required key prints a warning.
Source
src/config/load-wrangler.ts:889-919src/config/load-wrangler.ts:1435-1460src/runtime/bindings.test.ts:138-148
Supported.env secretsWhen no .dev.vars file exists, wrangler dev loads .env files into env as secret text.Orange gets the same behavior from Wrangler's unstable_getVarsForDev. A .env key reaches env as a string. 2 files
Notes
Orange passes no custom env file list, so Wrangler reads its default .env files. CLOUDFLARE_LOAD_DEV_VARS_FROM_DOT_ENV and CLOUDFLARE_INCLUDE_PROCESS_ENV apply as in Wrangler. Verified by loading a config with a .env file and no .dev.vars.
Not verified by a test
Not covered by a repository test. Verified once by a manual config load on the devbox.
Source
src/config/load-wrangler.ts:893-906src/config/load-wrangler.ts:1435-1460
Partialsecrets_store_secretsget() returns the secret value from the account Secrets Store.get() reads the value from .dev.vars in the project root, then from the host process.env. 4 files
Notes
Orange does not call the Secrets Store API and does not read .env files for this binding. A missing value rejects with Secrets Store binding "<NAME>" is not configured locally.
Source
src/config/load-wrangler.ts:767-773packages/runtime-node/src/runner.ts:572-574packages/runtime-node/src/bindings/secrets-store.ts:89-142src/commands/dev.test.ts:151
Partialversion_metadataenv binding with the Worker version id (a UUID), the version tag, and the version timestamp.id is a SHA-256 hex digest of the bundle and the normalized config. tag is always "dev". timestamp is the build time. 4 files
Partialunsafe.bindings unsafe_evalThe unsafe_eval binding has eval(), newFunction(), newAsyncFunction(), and newWasmModule().Wrangler emits unsafe_unsafe_eval, and Orange maps it to an UnsafeEval object built on node:vm. 3/4 pass · 3 files
Notes
unsafe-test passes 4 of 5. basics fails because a plain eval('') does not throw in Orange. Workerd forbids code generation outside the binding.
Tests
  • api-tests--unsafe-test › newFunction Pass
  • api-tests--unsafe-test › newAsyncFunction Pass
  • api-tests--unsafe-test › newWasmModule Pass
  • api-tests--unsafe-test › basics AssertionError [ERR_ASSERTION]: Missing expected exception. Fail · Behavior differs
Source
src/config/load-wrangler.ts:795-796packages/runtime-node/src/runner.ts:498-500packages/runtime-node/src/bindings/unsafe-eval.ts:22-53
Stubunsafe.bindings of a type other than unsafe_evalPasses a binding of any type through to the Workers runtime without Wrangler validation.Wrangler emits unsafe_<type>. Orange loads it as a stub that throws unsafe_<type> binding "<NAME>" is not supported by OpenOrange. See the OpenOrange bindings documentation for supported bindings. 6 files
Notes
Config load prints a [config-warning] line. Any member read returns a function that throws the message synchronously when called. Code that never calls the binding keeps working. The unsafe key is accepted only when it holds bindings and nothing else.
Source
src/config/load-wrangler.ts:534-538src/config/load-wrangler.ts:882-884src/config/load-wrangler.ts:757-763packages/runtime-node/src/runner.ts:645-647packages/runtime-node/src/bindings/unsupported.ts:75-98src/commands/dev.ts:207
Alternativekv_namespaces (Workers KV)Binds a Workers KV namespace: a global, eventually consistent key-value store with edge caching.Each namespace id is an Orange-internal SQLite Durable Object on Rivet Actors. Data persists under .open-orange/rivetkit across orange dev restarts. 0/1 pass · 7 files
Notes
Reads see writes at once. Cloudflare can take 60 seconds or more to show a write in other locations. Orange has no edge cache. The local id is preview_id, then id, then the binding name, like wrangler dev. Upstream kv-test fails 0 of 5 because the conformance runner drops workerd kvNamespace bindings, not because of Orange's KV.
Tests
  • api-tests--kv-test › getTest AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: | + actual - expected | Fail · Behavior differs
Source
src/config/load-wrangler.ts:797-802src/config/load-wrangler.ts:669-677packages/runtime-node/src/runner.ts:501-508packages/runtime-node/src/bindings/internal-objects.ts:12-21packages/runtime-node/src/bindings/kv/object.ts:6-10src/runtime/bindings.test.ts:175-286packages/cloudflare-conformance/src/upstream/run-file.ts:378-413
SupportedKV get()get(key) returns the value as text, or null when the key is absent.Same result. Key validation and error text follow workerd and Miniflare. 4 files
Notes
cacheTtl is validated (at least 30) and then ignored, because Orange has no cache. Expired keys read as null.
Source
packages/runtime-node/src/bindings/kv/namespace.ts:239-275packages/runtime-node/src/bindings/kv/object.ts:111-124src/runtime/bindings.test.ts:175-192src/runtime/bindings.test.ts:206-223
SupportedKV get() with a typeget(key, type) returns text, json, arrayBuffer, or stream values.Supports the same four types and rejects other types with workerd's error text. 3 files
SupportedKV getWithMetadata()Returns the value, its metadata, and cacheStatus.Returns value, metadata, and cacheStatus. 2 files
Notes
cacheStatus is always null, because Orange has no cache.
Source
packages/runtime-node/src/bindings/kv/namespace.ts:245-275src/runtime/bindings.test.ts:175-192
SupportedKV get() with an array of keysReturns a Map for up to 100 keys. Only text and json types are allowed.Same Map result, type rules, no Cloudflare key-count or size limit. 4 files
SupportedKV put() with expiration and metadataWrites a string, ArrayBuffer, ArrayBufferView, or stream with optional expiration, expirationTtl, and metadata.Accepts the same value types and options, without Cloudflare's key, value, metadata, or TTL limits. A put of 128 MiB or more fails with Rivet's commit limit. 5 files
SupportedKV delete()Deletes one key. Deleting an absent key succeeds.Deletes the row from the namespace's SQLite table. An absent key succeeds. 2 files
Notes
Key validation matches get() and put().
Not verified by a test
No repository test calls delete(). Verified by reading the code only.
Source
packages/runtime-node/src/bindings/kv/namespace.ts:359-364packages/runtime-node/src/bindings/kv/object.ts:138
SupportedKV list() with prefix, limit, and cursorLists keys in byte order with an opaque cursor, up to 1000 keys per page.Lists keys in UTF-8 byte order with prefix, limit, and cursor. Expired keys are left out. 3 files
Notes
The cursor is the base64url form of the last key. Code must treat it as opaque, as on Cloudflare.
Source
packages/runtime-node/src/bindings/kv/namespace.ts:366-386packages/runtime-node/src/bindings/kv/object.ts:187-220src/runtime/bindings.test.ts:193-204
N/AKV deleteBulk()Not deployed. Workerd adds deleteBulk() only with the experimental flag, for tests.KVNamespace has no deleteBulk() method. 0/1 pass · 1 file
Notes
kv-test deleteBulkTest fails because the runner drops the KV binding.
Tests
  • api-tests--kv-test › deleteBulkTest TypeError: env.KV.deleteBulk is not a function Fail · Behavior differs
Source
packages/runtime-node/src/bindings/kv/namespace.ts:232-387
Alternatived1_databases (D1)Binds a D1 database: managed SQLite with optional read replicas.Each database id is an Orange-internal SQLite Durable Object on Rivet Actors. Data persists under .open-orange/rivetkit across orange dev restarts. 7 files
Notes
Every query goes to one local primary, so there are no read replicas. The local id is preview_database_id, then database_id, then the binding name. The D1 client follows workerd's HTTP-based client, and the backend follows Miniflare's D1 backend. orange d1 migrations apply/list and orange d1 execute write the same local store that orange dev reads.
Source
src/config/load-wrangler.ts:803-808packages/runtime-node/src/runner.ts:584-591packages/runtime-node/src/bindings/internal-objects.ts:12-21packages/runtime-node/src/bindings/d1/database.ts:1-13packages/runtime-node/src/bindings/d1/object.ts:5-8src/runtime/bindings.test.ts:236-286src/commands/d1.test.ts:29-180
SupportedD1 prepare()Makes a prepared statement from SQL.Makes a statement that runs on the D1 Rivet Actor. 4 files
SupportedD1 bind()Binds numbers, strings, booleans, null, and byte arrays.Same conversions as workerd: booleans become 1 or 0, and ArrayBuffers become byte arrays. Other types fail with D1_TYPE_ERROR. 4 files
SupportedD1 first()Returns the first row, one column of it, or null.Same result. A missing column fails with D1_COLUMN_NOTFOUND: Column not found (<name>). 3 files
SupportedD1 all()Returns results and meta for a statement.Returns results and meta with changes, last_row_id, rows_read, rows_written, size_after, and duration. 3 files
SupportedD1 raw()Returns rows as arrays, with an optional first row of column names.Same result, including the columnNames option. 2 files
SupportedD1 run()Runs a statement and returns meta.Runs the statement through the /execute path and returns the backend result. 2 files
SupportedD1 batch()Runs statements in one transaction. A failure rolls back the whole batch.Runs the statements in one storage transaction. A failure rolls back the batch. 3 files
SupportedD1 exec()Runs raw SQL, one statement per line, and returns count and duration.Splits the input by line like workerd and reports the failing line in D1_EXEC_ERROR. 4 files
UnsupportedD1 dump()Deprecated. Returns the database file for databases from the D1 alpha.The backend has no dump route, so dump() always rejects with D1_DUMP_ERROR: Status + 404. 2 files
Notes
The error does not say that Orange does not support dump().
Not verified by a test
Not run. Follows from the backend routing only /query and /execute.
Source
packages/runtime-node/src/bindings/d1/database.ts:259-275packages/runtime-node/src/bindings/d1/object.ts:75-82
SupportedD1 withSession()Sessions give sequential consistency across read replicas.Sessions work. Every query reaches the one primary, so reads are always current. 4 files
SupportedD1 session getBookmark()Returns the latest bookmark of the session.Returns a local bookmark made from a timestamp and a counter. 4 files
Partialdurable_objects (class in this Worker)Binds a Durable Object class from this Worker. The class can use the SQLite or the KV storage backend.Binds the class when a new_sqlite_classes migration creates it. The namespace runs on Rivet Actors. 4 files
Notes
Classes from new_classes (KV backend) fail config load with Unsupported Durable Object migration fields. See the Durable Object entries for API details.
Source
src/config/load-wrangler.ts:1036-1043src/config/load-wrangler.ts:921-944packages/runtime-node/src/runner.ts:681-693src/config/load-wrangler.test.ts:92-134
Supporteddurable_objects (class in another Worker)Binds a Durable Object class that another Worker exports, with script_name.The class runs in the Worker named by script_name, in the same orange dev session and on the same Rivet Engine. Stubs from both Workers reach one object. 3 files
Notes
A script_name outside the session gives a namespace whose stubs answer fetch() with 503 and throw on RPC, like Wrangler's dev registry. A binding with only environment or namespace_id still loads a stub.
Source
packages/runtime-node/src/session/client.tspackages/runtime-node/src/session/server.tssrc/runtime/multi-worker.test.ts
Supportedservices (this Worker's default entrypoint)A service binding can target the Worker itself.A binding whose service equals the config name calls the default export in process. 1/1 pass · 3 files
Notes
The config must set name. Without name, Orange treats every service binding as a binding to another Worker and loads a stub.
Tests
  • api-tests--js-rpc-test › basicServiceBinding Pass
Source
src/config/load-wrangler.ts:776-786packages/runtime-node/src/runtime.ts:133-144packages/runtime-node/src/bindings/service.ts:50-67
Partialservices with entrypoint (named entrypoint in this Worker)entrypoint selects a named WorkerEntrypoint export of the target Worker.Calls the named export of this Worker. A missing export fails with Worker has no entrypoint named "<name>". 0/2 pass · 2 files
Notes
The repository end-to-end test passes. Upstream namedServiceBinding hangs for 60 seconds in all four js-rpc test files.
Not verified by a test
The cause of the namedServiceBinding hang is not found.
Tests
  • api-tests--js-rpc-test › namedServiceBinding TimeoutError: The operation was aborted due to timeout Fail · Hangs (60s timeout)
  • api-tests--js-rpc-socket-test › namedServiceBinding TimeoutError: The operation was aborted due to timeout Fail · Hangs (60s timeout)
Source
packages/runtime-node/src/bindings/service.ts:81-157src/runtime/service-binding.test.ts:49
Supportedservices with propsprops on a service binding appear as ctx.props in the target entrypoint.Config props and ctx.exports.<Name>({ props }) reach ctx.props. Overlapping calls see only their own props. 1/1 pass · 4 files
Notes
ctx-props-test fails only its ctx-props-test-disabled case, which tests a Worker without the props flag.
Tests
  • api-tests--ctx-props-test › ctx-props-test-disabled Pass
Source
src/config/load-wrangler.ts:782packages/runtime-node/src/bindings/service.ts:97-124packages/runtime-node/src/bindings/service.ts:477-492packages/runtime-node/src/bindings/service.test.ts:316-354
SupportedService binding fetch()fetch() on a service binding sends an HTTP request to the target's fetch handler.Calls the entrypoint's fetch() in process. It follows redirects like workerd's fetch() and passes caller aborts to the callee. 3 files
PartialService binding JS RPCMethods and properties of a WorkerEntrypoint are callable over JS RPC.Each call gets a new entrypoint instance in process. js-rpc-test passes 28 of 33. 3/5 pass · 2 files
Notes
Fails: disposal (not implemented), namedServiceBinding and portAbortCall (hang), sendStubOverRpc, and serializeHttpTypes. See the runtime API entries for RPC details.
Tests
  • api-tests--js-rpc-test › basicServiceBinding Pass
  • api-tests--js-rpc-test › disposal Pass
  • api-tests--js-rpc-test › portAbortCall Pass
  • api-tests--js-rpc-test › sendStubOverRpc AssertionError [ERR_ASSERTION]: Missing expected rejection (Error). Fail · Behavior differs
  • api-tests--js-rpc-test › serializeHttpTypes AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: | + actual - expected | Fail · Behavior differs
Source
packages/runtime-node/src/bindings/service.ts:159-216packages/runtime-node/src/rpc/loopback.ts
SupportedService binding connect()connect() opens a socket to the target Worker's connect handler.Opens an in-process socket to the entrypoint's connect() handler of this Worker. In a Durable Object, the connection opens after earlier writes are durable. The handler's end closes when its promise settles. 3/3 pass · 3 files
Notes
A target without connect() fails with Handler does not export a connect() function. A binding to another Worker is a stub (see Service binding to another Worker). js-rpc-test connectBinding passes. connect-handler-test localAddressViaServiceBinding fails only because the conformance runner drops its binding.
Tests
  • api-tests--js-rpc-test › connectBinding Pass
  • api-tests--connect-handler-test › localAddressViaServiceBinding Pass
  • api-tests--connect-neuter-test › connectNeuterRegression Pass
Source
packages/runtime-node/src/bindings/service.ts:330-366packages/runtime-node/src/bindings/service.ts:455-457packages/runtime-node/src/bindings/service.test.ts:355
Partialservices (another Worker)Calls a different Worker over fetch, JS RPC, or connect().orange dev -c a -c b runs both Workers. fetch() and JS RPC reach the other Worker's default or named entrypoint over loopback HTTP. A Worker outside the session answers 503 on fetch() and throws on RPC with Wrangler's dev registry message. 3 files
Notes
connect() and WebSocket upgrades to another Worker throw. Workers in separate orange dev processes do not find each other.
Workaround
Pass every Worker to one orange dev with repeated -c.
Source
packages/runtime-node/src/session/client.tspackages/runtime-node/src/session/server.tssrc/runtime/multi-worker.test.ts
Supportedctx.exports loopback bindingsctx.exports exposes this Worker's entrypoints as service stubs and its Durable Object classes as namespaces.Builds ctx.exports from the Worker's named exports: entrypoints become loopback service stubs, and Durable Object classes become namespaces, including classes without a binding. 1/1 pass · 4 files
Notes
ctx.exports in a Durable Object throws DurableObjectState.exports is not implemented. import { exports } from "cloudflare:workers" reads the same object.
Tests
  • api-tests--importable-exports-test › importableExports Pass
Source
packages/runtime-node/src/bindings/service.ts:529-554packages/runtime-node/src/runtime.ts:168-175packages/runtime-node/src/runner.ts:649-674packages/runtime-node/src/bindings/durable-objects/state.ts:374-378
Partialimport { env } from "cloudflare:workers"The env object is importable at module scope and in handlers.The importable env is the same object as the handler env, readable while the module evaluates. 0/2 pass · 2 files
Notes
importable-env-test fails because the runner drops its KV binding. disable-importable-env-test fails because Orange ignores the disallow_importable_env flag.
Tests
  • api-tests--importable-env-test › importableEnv 🍊 open-orange v0.0.1 · by rivet.dev | | Worker api-tests--importable-env-test Fail · File fails at load
  • api-tests--disable-importable-env-test › test 🍊 open-orange v0.0.1 · by rivet.dev | | Worker api-tests--disable-importable-env-test Fail · File fails at load
Source
packages/runtime-node/src/modules/cloudflare-workers/env.ts:38-85packages/runtime-node/src/runtime.ts:145-146
Supportedassets bindingassets.binding gives the Worker a Fetcher for its static assets.env.ASSETS.fetch() serves the assets directory with not_found_handling and follows redirects like a Fetcher. 3 files
Alternativesend_emailSends email from the Worker through Email Routing.With ORANGE_EMAIL_SMTP_URL set to an smtp:// or smtps:// URL, send() delivers through that SMTP server. It takes an EmailMessage with its own MIME, or a message object with from, to, cc, bcc, replyTo, subject, text, html, headers, and attachments, and returns { messageId }. destination_address, allowed_destination_addresses, and allowed_sender_addresses are checked before anything is sent. 7 files
Notes
Without ORANGE_EMAIL_SMTP_URL, the binding is a stub whose calls throw Send Email binding "<NAME>" is not supported by OpenOrange. Set ORANGE_EMAIL_SMTP_URL to your SMTP server, or send email through your provider's HTTP API with fetch(). When the server fails, send() throws an error that names the server without its credentials. Orange does not check sender domains or verified destinations. Incoming email handlers are a handler entry. See docs/modules/email.mdx.
Source
src/config/load-wrangler.ts:934-948packages/runtime-node/src/runner.ts:602-609packages/runtime-node/src/bindings/email/send-email.ts:94-128packages/runtime-node/src/bindings/email/smtp.ts:22-54packages/runtime-node/src/bindings/unsupported.ts:31-35tests/orange-email.test.ts:15-105docs/modules/email.mdx:82-87
Stubwasm_modules (wasm_module)Binds a WebAssembly module to a global in service-worker syntax Workers.Loads a stub that throws Wasm module binding "<NAME>" is not supported by OpenOrange. Import the WebAssembly module from the Worker source instead. 6 files
Notes
Config load prints a [config-warning] line. Any member read returns a function that throws the message synchronously when called. Code that never calls the binding keeps working. ES module Workers import .wasm files instead.
Workaround
Import the WebAssembly module from the Worker source instead.
Source
packages/runtime-node/src/bindings/unsupported.ts:42-45src/config/load-wrangler.ts:882-884src/config/load-wrangler.ts:757-763packages/runtime-node/src/runner.ts:645-647packages/runtime-node/src/bindings/unsupported.ts:75-98src/commands/dev.ts:207
Stubtext_blobs (text_blob)Binds a text file to a global in service-worker syntax Workers.Loads a stub that throws Text blob binding "<NAME>" is not supported by OpenOrange. See the OpenOrange bindings documentation for supported bindings. 6 files
Notes
Config load prints a [config-warning] line. Any member read returns a function that throws the message synchronously when called. Code that never calls the binding keeps working. ES module Workers import text modules instead.
Source
packages/runtime-node/src/bindings/unsupported.ts:38src/config/load-wrangler.ts:882-884src/config/load-wrangler.ts:757-763packages/runtime-node/src/runner.ts:645-647packages/runtime-node/src/bindings/unsupported.ts:75-98src/commands/dev.ts:207
Stubdata_blobs (data_blob)Binds a binary file to a global in service-worker syntax Workers.Loads a stub that throws Data blob binding "<NAME>" is not supported by OpenOrange. See the OpenOrange bindings documentation for supported bindings. 6 files
Notes
Config load prints a [config-warning] line. Any member read returns a function that throws the message synchronously when called. Code that never calls the binding keeps working. ES module Workers import data modules instead.
Source
packages/runtime-node/src/bindings/unsupported.ts:14src/config/load-wrangler.ts:882-884src/config/load-wrangler.ts:757-763packages/runtime-node/src/runner.ts:645-647packages/runtime-node/src/bindings/unsupported.ts:75-98src/commands/dev.ts:207
AlternativebrowserGives the Worker a headless browser through Browser Rendering.With ORANGE_BROWSER_CDP_URL set to a Chrome DevTools Protocol endpoint (ws://, wss://, or an http:// address whose /json/version names one), the binding answers the requests of @cloudflare/puppeteer 1.x: launch(), the DevTools WebSocket of a session, sessions(), history(), and limits(). 6 files
Notes
Without ORANGE_BROWSER_CDP_URL, the binding is a stub whose calls throw Browser Rendering binding "<NAME>" is not supported by OpenOrange. Set ORANGE_BROWSER_CDP_URL to a Chrome DevTools Protocol endpoint. Sessions on one self-run browser share it and its cookies, and browser.close() closes only the session's pages. keep_alive, location, and recording are ignored, and session limits are not enforced. See docs/modules/browser-rendering.mdx.
Source
src/config/load-wrangler.ts:932-933packages/runtime-node/src/runner.ts:597-601packages/runtime-node/src/bindings/browser/browser.ts:219-326packages/runtime-node/src/bindings/unsupported.ts:13-19tests/orange-browser.test.ts:102-159docs/modules/browser-rendering.mdx:109-124
Alternativeworkflows (workflow)Creates and controls Workflow instances that run durable steps, sleeps, and event waits.Each instance is a Durable Object of the Orange-internal class openorange:workflow-engine on a Rivet Actor, running Cloudflare's Workflows engine from workers-sdk (workflows-shared at 4a5377fc), the engine of wrangler dev. create(), createBatch(), get(), deleteBatch(), and status(), pause(), resume(), terminate(), restart() (also from a step), delete(), and sendEvent() work. Steps awaited together run concurrently. The earliest timer is the object's alarm, so instances continue after their actor sleeps and across orange dev restarts. 7 files
Notes
Step output is bounded by Rivet's 128 MiB commit, not Cloudflare's 1 MiB. A duplicate ID is rejected, also for concurrent creates. Errors keep their names, as workerd's RPC keeps them from compatibility date 2026-04-21; wrangler dev's engine runs on 2024-10-22 and renames them. The status waiting is reported whenever the run only waits. limits.steps and subscribe() are not implemented. terminate() cannot stop a step callback that is already running. A binding with another Worker's script_name runs the Workflow in that Worker of the orange dev session. See docs/modules/workflows.mdx.
Source
src/config/load-wrangler.ts:842-851packages/runtime-node/src/runner.ts:599-645packages/runtime-node/src/bindings/workflows/binding.ts:92-346packages/runtime-node/src/bindings/workflows/engine-object.ts:222-542packages/runtime-node/src/bindings/workflows/engine-wake.ts:1-35src/runtime/workflows.test.ts:56-579tests/examples.test.ts:175-215
Alternativequeues.producers (queue)Sends messages to a Cloudflare Queue.Each queue is an Orange-internal Rivet Actor whose RivetKit queue stores the messages. send() and sendBatch() with the text, bytes, json, and v8 content types, delaySeconds, delivery_delay, and metrics() work, and messages persist across orange dev restarts. 0/1 pass · 5 files
Notes
Cloudflare's message and batch limits are not copied. One send() or sendBatch() is one message to the Rivet Engine, at most 32 MiB. The registry raises maxIncomingMessageSize to 32 MiB so that one sendBatch() fits in one action request. Upstream queue-test fails because the conformance runner drops its queue binding. See docs/modules/queues.mdx.
Tests
  • api-tests--queue-test › queue-test TypeError: Expected one of body or serializedBody for each message Fail · Behavior differs
Source
src/config/load-wrangler.ts:821-833packages/runtime-node/src/runner.ts:540-549packages/runtime-node/src/bindings/queues/producer.ts:88-175packages/runtime-node/src/internal-actors/queue.ts:301-344src/runtime/queues.test.ts:139-337
Alternativer2_buckets (r2_bucket)Reads and writes objects in an R2 bucket.Each bucket_name is an Orange-internal SQLite Durable Object on Rivet Actors that stores bodies in 512 KiB chunks. head(), get(), put(), delete(), list(), conditional and range requests, checksums, and multipart uploads work, and objects persist across orange dev restarts. A bucket can use an S3-compatible store instead through ORANGE_R2_<BUCKET>_S3_* variables. 1/2 pass · 7 files
Notes
On the default backend, one Rivet Actor stores each bucket, so Rivet's storage limit for one actor bounds the bucket. ssecKey throws NotSupportedError. Puts accept streams of any length. The S3 backend restores custom metadata key case from an orange-r2-key-case metadata entry. Upstream r2-test fails because the conformance runner drops workerd's r2Bucket binding. See docs/modules/r2.mdx.
Tests
  • api-tests--r2-test › r2-test AssertionError [ERR_ASSERTION]: Expected values to be loosely deep-equal: | | { Fail · Behavior differs
  • api-tests--r2-write-http-metadata-validation-test › writeHttpMetadataValidation Pass
Source
src/config/load-wrangler.ts:813-820packages/runtime-node/src/runner.ts:526-539packages/runtime-node/src/bindings/r2/bucket.ts:166-294packages/runtime-node/src/bindings/r2/storage.ts:23-28packages/runtime-node/src/bindings/r2/storage.ts:192-737packages/runtime-node/src/bindings/r2/s3-backend.ts:302-627src/runtime/r2.test.ts:224-501
Partialanalytics_engine_datasets (analytics_engine)Writes data points to a Workers Analytics Engine dataset.writeDataPoint() accepts data points and drops them, as Miniflare does in local development. 0/1 pass · 4 files
Notes
There is nothing to query. Upstream analytics-engine-test still fails because the conformance runner drops its binding.
Workaround
Write data points to a Durable Object or D1 database if you need to read them back.
Tests
  • api-tests--analytics-engine-test › main Error: Test never received request from analytics engine handler Fail · Behavior differs
Source
packages/runtime-node/src/bindings/analytics-engine.ts:1-6src/config/load-wrangler.ts:838-839packages/runtime-node/src/runner.ts:460-462src/commands/dev.test.ts:499-547
Partialdispatch_namespaces (dispatch_namespace)Calls user Workers in a Workers for Platforms dispatch namespace.get(name) returns a Fetcher for the Worker of the orange dev session with that name. A missing Worker throws Worker not found. 3 files
Notes
args, limits, and outbound Workers have no effect. Namespace membership is not checked.
Workaround
Pass user Workers to orange dev with repeated -c.
Source
packages/runtime-node/src/session/client.tspackages/runtime-node/src/session/server.tssrc/runtime/multi-worker.test.ts
Stubmtls_certificates (mtls_certificate)Presents a client certificate on outbound fetch() calls.Loads a stub that throws mTLS certificate binding "<NAME>" is not supported by OpenOrange. See the OpenOrange bindings documentation for supported bindings. 6 files
Notes
Config load prints a [config-warning] line. Any member read returns a function that throws the message synchronously when called. Code that never calls the binding keeps working.
Source
packages/runtime-node/src/bindings/unsupported.ts:31src/config/load-wrangler.ts:882-884src/config/load-wrangler.ts:757-763packages/runtime-node/src/runner.ts:645-647packages/runtime-node/src/bindings/unsupported.ts:75-98src/commands/dev.ts:207
StublogfwdrForwards logs to a configured destination. This is an internal Cloudflare binding.Loads a stub that throws Log forwarding binding "<NAME>" is not supported by OpenOrange. See the OpenOrange bindings documentation for supported bindings. 6 files
Notes
Config load prints a [config-warning] line. Any member read returns a function that throws the message synchronously when called. Code that never calls the binding keeps working.
Source
packages/runtime-node/src/bindings/unsupported.ts:29src/config/load-wrangler.ts:882-884src/config/load-wrangler.ts:757-763packages/runtime-node/src/runner.ts:645-647packages/runtime-node/src/bindings/unsupported.ts:75-98src/commands/dev.ts:207
AlternativeaiRuns models on Workers AI.A port of workerd's Ai client sends each run() to an OpenAI-compatible provider, OpenRouter by default, set with ORANGE_AI_BASE_URL and ORANGE_AI_API_KEY. Text generation, streams, tool calls, and embeddings work for the built-in @cf model table and for models added with ORANGE_AI_MODELS. 5 files
Notes
The text comes from another host. A model without a mapping, and image, speech, translation, and reranker models, throw an error that names ORANGE_AI_MODELS. The gateway option goes to the provider directly. env.AI.gateway(), autorag(), aiSearch(), and toMarkdown() throw NotSupportedError. See docs/modules/workers-ai.mdx.
Source
src/config/load-wrangler.ts:811-812packages/runtime-node/src/runner.ts:451-459packages/runtime-node/src/bindings/ai/ai.ts:61-188packages/runtime-node/src/bindings/ai/backend.ts:401-559src/runtime/ai-binding.test.ts:243-438
StubimagesTransforms and stores images with Cloudflare Images.Loads a stub that throws Images binding "<NAME>" is not supported by OpenOrange. See the OpenOrange bindings documentation for supported bindings. 6 files
Notes
Config load prints a [config-warning] line. Any member read returns a function that throws the message synchronously when called. Code that never calls the binding keeps working.
Source
packages/runtime-node/src/bindings/unsupported.ts:28src/config/load-wrangler.ts:882-884src/config/load-wrangler.ts:757-763packages/runtime-node/src/runner.ts:645-647packages/runtime-node/src/bindings/unsupported.ts:75-98src/commands/dev.ts:207
StubstreamManages videos in Cloudflare Stream.Loads a stub that throws Stream binding "<NAME>" is not supported by OpenOrange. See the OpenOrange bindings documentation for supported bindings. 6 files
Notes
Config load prints a [config-warning] line. Any member read returns a function that throws the message synchronously when called. Code that never calls the binding keeps working.
Source
packages/runtime-node/src/bindings/unsupported.ts:37src/config/load-wrangler.ts:882-884src/config/load-wrangler.ts:757-763packages/runtime-node/src/runner.ts:645-647packages/runtime-node/src/bindings/unsupported.ts:75-98src/commands/dev.ts:207
StubmediaTransforms video and audio with Media Transformations.Loads a stub that throws Media Transformations binding "<NAME>" is not supported by OpenOrange. See the OpenOrange bindings documentation for supported bindings. 6 files
Notes
Config load prints a [config-warning] line. Any member read returns a function that throws the message synchronously when called. Code that never calls the binding keeps working.
Source
packages/runtime-node/src/bindings/unsupported.ts:30src/config/load-wrangler.ts:882-884src/config/load-wrangler.ts:757-763packages/runtime-node/src/runner.ts:645-647packages/runtime-node/src/bindings/unsupported.ts:75-98src/commands/dev.ts:207
SupportedhyperdriveGives a pooled, cached connection string for a remote database.Exposes connectionString, host, port, user, password, database, and connect() for the local database, like wrangler dev. Reads CLOUDFLARE_HYPERDRIVE_LOCAL_CONNECTION_STRING_<BINDING> (or the deprecated WRANGLER_ prefix), then localConnectionString. 4 files
Notes
Connects directly; no connection pooling or query caching. A missing connection string fails startup with the Wrangler error. host and port name the database itself, not a Hyperdrive proxy.
Source
packages/runtime-node/src/bindings/hyperdrive.ts:1-84src/config/load-wrangler.ts:706-748packages/runtime-node/src/runner.ts:466-468tests/hyperdrive.test.ts
StubvectorizeQueries and writes vectors in a Vectorize index.Loads a stub that throws Vectorize binding "<NAME>" is not supported by OpenOrange. See the OpenOrange bindings documentation for supported bindings. 6 files
Notes
Config load prints a [config-warning] line. Any member read returns a function that throws the message synchronously when called. Code that never calls the binding keeps working.
Source
packages/runtime-node/src/bindings/unsupported.ts:39src/config/load-wrangler.ts:882-884src/config/load-wrangler.ts:757-763packages/runtime-node/src/runner.ts:645-647packages/runtime-node/src/bindings/unsupported.ts:75-98src/commands/dev.ts:207
Stubai_search_namespaces (ai_search_namespace)Manages AI Search instances in one namespace.Loads a stub that throws AI Search namespace binding "<NAME>" is not supported by OpenOrange. See the OpenOrange bindings documentation for supported bindings. 6 files
Notes
Config load prints a [config-warning] line. Any member read returns a function that throws the message synchronously when called. Code that never calls the binding keeps working.
Source
packages/runtime-node/src/bindings/unsupported.ts:12src/config/load-wrangler.ts:882-884src/config/load-wrangler.ts:757-763packages/runtime-node/src/runner.ts:645-647packages/runtime-node/src/bindings/unsupported.ts:75-98src/commands/dev.ts:207
StubwebsearchQueries Cloudflare Web Search.Loads a stub that throws websearch binding "<NAME>" is not supported by OpenOrange. See the OpenOrange bindings documentation for supported bindings. 5 files
Notes
Config load prints a [config-warning] line. Any member read returns a function that throws the message synchronously when called. Code that never calls the binding keeps working.
Source
src/config/load-wrangler.ts:882-884src/config/load-wrangler.ts:757-763packages/runtime-node/src/runner.ts:645-647packages/runtime-node/src/bindings/unsupported.ts:75-98src/commands/dev.ts:207
Stubagent_memoryReads and writes an Agent Memory namespace.Loads a stub that throws agent_memory binding "<NAME>" is not supported by OpenOrange. See the OpenOrange bindings documentation for supported bindings. 5 files
Notes
Config load prints a [config-warning] line. Any member read returns a function that throws the message synchronously when called. Code that never calls the binding keeps working.
Source
src/config/load-wrangler.ts:882-884src/config/load-wrangler.ts:757-763packages/runtime-node/src/runner.ts:645-647packages/runtime-node/src/bindings/unsupported.ts:75-98src/commands/dev.ts:207
Stubpipelines (pipeline)Sends records to a Cloudflare Pipeline.Loads a stub that throws Pipelines binding "<NAME>" is not supported by OpenOrange. See the OpenOrange bindings documentation for supported bindings. 6 files
Notes
Config load prints a [config-warning] line. Any member read returns a function that throws the message synchronously when called. Code that never calls the binding keeps working.
Source
packages/runtime-node/src/bindings/unsupported.ts:32src/config/load-wrangler.ts:882-884src/config/load-wrangler.ts:757-763packages/runtime-node/src/runner.ts:645-647packages/runtime-node/src/bindings/unsupported.ts:75-98src/commands/dev.ts:207
StubartifactsReads and writes git-compatible file storage in Artifacts.Loads a stub that throws artifacts binding "<NAME>" is not supported by OpenOrange. See the OpenOrange bindings documentation for supported bindings. 5 files
Notes
Config load prints a [config-warning] line. Any member read returns a function that throws the message synchronously when called. Code that never calls the binding keeps working.
Source
src/config/load-wrangler.ts:882-884src/config/load-wrangler.ts:757-763packages/runtime-node/src/runner.ts:645-647packages/runtime-node/src/bindings/unsupported.ts:75-98src/commands/dev.ts:207
StubflagshipReads feature flags from Flagship.Loads a stub that throws flagship binding "<NAME>" is not supported by OpenOrange. See the OpenOrange bindings documentation for supported bindings. 5 files
Notes
Config load prints a [config-warning] line. Any member read returns a function that throws the message synchronously when called. Code that never calls the binding keeps working.
Source
src/config/load-wrangler.ts:882-884src/config/load-wrangler.ts:757-763packages/runtime-node/src/runner.ts:645-647packages/runtime-node/src/bindings/unsupported.ts:75-98src/commands/dev.ts:207
Alternativeratelimits (ratelimit)Applies a rate limit with the Workers Rate Limiting API.Each namespace_id is an Orange-internal SQLite Durable Object on Rivet Actors with a fixed-window counter, like Miniflare. Counts persist under .open-orange/rivetkit across orange dev restarts. 5 files
Notes
Accepts ratelimits and unsafe.bindings with type ratelimit. Config load rejects a period other than 10 or 60 and a limit that is not a number, like wrangler dev. Cloudflare counts per location and can allow more than the limit; Orange keeps one exact counter per namespace_id. Each limit() call is one actor round trip.
Source
src/config/load-wrangler.ts:679-704packages/runtime-node/src/runner.ts:592-600packages/runtime-node/src/bindings/ratelimit/object.ts:3-9packages/runtime-node/src/bindings/ratelimit/binding.ts:4-7src/runtime/bindings.test.ts:288-400
Partialworker_loaders (worker_loader)Loads and runs dynamic Workers from code at runtime.Each dynamic Worker runs in its own Node.js process. get() caches by name, load() and get(null) start fresh Workers. fetch(), RPC, env and props capabilities, globalOutbound null or Fetcher, and js/cjs/text/data/json/wasm modules work. 2 files
Notes
getDurableObjectClass(), entrypoint connect(), Python modules, and compiled WebAssembly.Module values throw. Compatibility settings, limits, and tails are ignored. See docs/modules/worker-loader.mdx.
Source
packages/runtime-node/src/bindings/worker-loader/loader.tssrc/runtime/worker-loader.test.ts
Stubvpc_services (vpc_service)Reaches a private service through Workers VPC.Loads a stub that throws VPC service binding "<NAME>" is not supported by OpenOrange. See the OpenOrange bindings documentation for supported bindings. 6 files
Notes
Config load prints a [config-warning] line. Any member read returns a function that throws the message synchronously when called. Code that never calls the binding keeps working.
Source
packages/runtime-node/src/bindings/unsupported.ts:41src/config/load-wrangler.ts:882-884src/config/load-wrangler.ts:757-763packages/runtime-node/src/runner.ts:645-647packages/runtime-node/src/bindings/unsupported.ts:75-98src/commands/dev.ts:207
Stubvpc_networks (vpc_network)Reaches a private network through Workers VPC.Loads a stub that throws VPC network binding "<NAME>" is not supported by OpenOrange. See the OpenOrange bindings documentation for supported bindings. 6 files
Notes
Config load prints a [config-warning] line. Any member read returns a function that throws the message synchronously when called. Code that never calls the binding keeps working.
Source
packages/runtime-node/src/bindings/unsupported.ts:40src/config/load-wrangler.ts:882-884src/config/load-wrangler.ts:757-763packages/runtime-node/src/runner.ts:645-647packages/runtime-node/src/bindings/unsupported.ts:75-98src/commands/dev.ts:207
Stubunsafe_hello_worldAn example binding in Wrangler's schema. Wrangler marks it as do not use.Loads a stub that throws unsafe_hello_world binding "<NAME>" is not supported by OpenOrange. See the OpenOrange bindings documentation for supported bindings. 5 files
Notes
Config load prints a [config-warning] line. Any member read returns a function that throws the message synchronously when called. Code that never calls the binding keeps working.
Source
src/config/load-wrangler.ts:882-884src/config/load-wrangler.ts:757-763packages/runtime-node/src/runner.ts:645-647packages/runtime-node/src/bindings/unsupported.ts:75-98src/commands/dev.ts:207

Handlers

Supportedfetch handler (object default export)export default { fetch(request, env, ctx) } handles each HTTP request.Each inbound HTTP request calls fetch(request, env, ctx) with a new ExecutionContext. 1/1 pass · 3 files
Notes
A handler that throws gives a plain-text 500 Internal Server Error, not the Cloudflare 1101 error page. A non-Response result fails with Worker fetch handler must return a Response.
Tests
  • api-tests--fetch-test › test Pass
Source
packages/runtime-node/src/runtime.ts:75-82packages/runtime-node/src/events/fetch.ts:27-61packages/runtime-node/src/runner.ts:951-1015
Supportedfetch handler (WorkerEntrypoint class default export)export default class extends WorkerEntrypoint { fetch(request) } creates an instance per request.Constructs the class with (ctx, env) for each request and calls its fetch(request). 1/1 pass · 2 files
Notes
A class without fetch() loads, and each request fails with Handler does not export a fetch() function., as in workerd.
Tests
  • api-tests--js-rpc-test › defaultExportClass Pass
Source
packages/runtime-node/src/runtime.ts:65-76packages/runtime-node/src/runtime.ts:154-159
PartialNamed WorkerEntrypoint exportsNamed entrypoint exports receive fetch, RPC, and connect calls from service bindings, including bindings from other Workers.Named entrypoints receive fetch, RPC, and connect calls from this Worker's own service bindings and ctx.exports. 2/3 pass · 2 files
Notes
Other Workers cannot call them, because cross-Worker service bindings are stubs. js-rpc-test namedServiceBinding times out (cause not checked). extendingEntrypointClasses and testConstructEntrypoint pass.
Not verified by a test
The cause of the namedServiceBinding timeout is not checked.
Tests
  • api-tests--js-rpc-test › extendingEntrypointClasses Pass
  • api-tests--js-rpc-test › testConstructEntrypoint Pass
  • api-tests--js-rpc-test › namedServiceBinding TimeoutError: The operation was aborted due to timeout Fail · Hangs (60s timeout)
Source
packages/runtime-node/src/bindings/service.ts:97-130packages/runtime-node/src/bindings/service.ts:529-553
Partialscheduled handlerCron Triggers in triggers.crons call scheduled(controller, env, ctx).One Orange-internal Rivet Actor holds a Rivet cron job per triggers.crons expression and calls scheduled(controller, env, ctx) on each due minute. /cdn-cgi/local/scheduled and /__scheduled (with --test-scheduled) run it on demand. 1/1 pass · 4 files
Notes
orange dev runs crons automatically, where wrangler dev does not. A tick that arrives while the previous run of the same cron still runs is skipped. noRetry() has no effect. Fetcher.scheduled() is not available: http-server-nodejs-test testScheduled fails with The RPC receiver does not implement the method "scheduled". See docs/modules/cron-triggers.mdx.
Tests
  • node-tests--http-server-nodejs-test › testScheduled Pass
Source
packages/runtime-node/src/events/scheduled.ts:61-91packages/runtime-node/src/internal-actors/cron.ts:94-160packages/runtime-node/src/runner.ts:454-486src/runtime/cron-triggers.test.ts:208-356
Partialqueue handlerQueue consumers in queues.consumers call queue(batch, env, ctx).The queue actor of each queue in queues.consumers delivers batches to queue(batch, env, ctx), one batch at a time. ack(), retry(), ackAll(), retryAll(), max_retries, retry delays, and dead_letter_queue follow Cloudflare's rules, and delivery is at least once. 1/1 pass · 6 files
Notes
max_concurrency is ignored. After an idle period, the first batch waits the whole max_batch_timeout. A queue is shared by name across the orange dev session, so a consumer in another Worker of the session receives the messages. orange dev fails at startup when two Workers declare a consumer for one queue. queue-metadata-test fails because the conformance runner drops its queue binding. See docs/modules/queues.mdx.
Tests
  • api-tests--queue-metadata-test › queue-metadata-test Pass
Source
packages/runtime-node/src/events/queue.ts:57-83packages/runtime-node/src/internal-actors/queue.ts:244-299packages/runtime-node/src/bindings/queues/batch.ts:112-163src/runtime/queues.test.ts:139-337packages/runtime-node/src/runner.ts:818-831src/runtime/multi-worker.test.ts:148-225
Partialemail handlerEmail Routing calls email(message, env, ctx) for inbound mail.A message POSTed to /cdn-cgi/handler/email, the route that wrangler dev serves, runs email(message, env, ctx): raw MIME with ?from=&to= in the URL, or a SendGrid or Mailgun inbound webhook. message.forward() and message.reply() send through ORANGE_EMAIL_SMTP_URL, and setReject() answers 400. 8 files
Notes
Email Routing is Cloudflare-only, so mail reaches the Worker only when your email provider's inbound webhook, or a script, POSTs it to the route. orange serve serves the route only when ORANGE_EMAIL_INBOUND_SECRET is set, and a wrong or missing secret gets 401. orange dev serves it without the secret, and checks the secret when it is set. forward() and reply() throw when ORANGE_EMAIL_SMTP_URL is not set. See docs/modules/email.mdx.
Source
packages/runtime-node/src/runner.ts:1145-1161packages/runtime-node/src/runtime.ts:196-202packages/runtime-node/src/events/email.ts:17-32packages/runtime-node/src/events/email.ts:66-98packages/runtime-node/src/events/email.ts:145-170packages/runtime-node/src/events/email.ts:172-256tests/email-handler.test.ts:11-58tests/orange-email.test.ts:106-160
Partialtail handlerA Tail Worker receives trace events from producer Workers that list it in tail_consumers.tail_consumers that name the Worker itself or another Worker of the orange dev session get one TraceItem per fetch, service binding fetch(), scheduled, or queue event, with logs, errorInfo, exceptions, outcome, and redacted request details as in workerd. 2/2 pass · 2 files
Notes
Durable Object events, JS RPC calls, and alarms are not traced. cpuTime is 0. tests/tail-consumers.test.ts compares a self and a cross-Worker consumer with workerd 1.20260903.1. See docs/modules/tail-workers.mdx.
Tests
  • api-tests--errorinfo-tail-test › test Pass
  • api-tests--tail-cf-gc-test › tailRequestCfCollects Pass
Source
packages/runtime-node/src/internal/tail-trace.ts:1-80packages/runtime-node/src/events/tail.ts:1-40
UnsupportedtailStream handlerA streaming Tail Worker receives live trace events from Workers that list it in streaming_tail_consumers.The Worker loads and the tailStream() handler never runs. 2 files
Notes
streaming_tail_consumers still fails config load.
Source
packages/runtime-node/src/runtime.ts:65-82src/config/load-wrangler.ts:651-662
Unsupportedtrace handlertrace is the legacy name of the tail handler.The Worker loads and the trace() handler never runs. 1 file
Notes
No trace events are produced.
Source
packages/runtime-node/src/runtime.ts:65-82
N/Atest handlerCloudflare does not deploy test handlers. workerd calls them only in its own test runner.The Worker loads and the test() handler never runs. 1 file
Notes
The conformance runner adapts upstream test handlers itself.
Source
packages/runtime-node/src/runtime.ts:65-82
Partialconnect handler (default export)connect(socket, env, ctx) handles inbound TCP connections from listeners in the connect config key and from Fetcher.connect().connect() runs only when this Worker's own service binding or ctx.exports calls connect(). Orange opens no TCP listener. 1/3 pass · 2 files
Notes
The connect config key fails config load. connect-handler-test connectHandler and connectHandlerProxy fail because nothing listens on the TCP port. js-rpc-test connectBinding passes.
Tests
  • api-tests--js-rpc-test › connectBinding Pass
  • api-tests--connect-handler-test › connectHandler Error: proxy request failed, cannot connect to the specified address Fail · Behavior differs
  • api-tests--connect-handler-test › connectHandlerProxy Error: proxy request failed, cannot connect to the specified address Fail · Behavior differs
Source
packages/runtime-node/src/bindings/service.ts:330-366src/config/load-wrangler.ts:544-552
Partialconnect handler (named entrypoint)A named WorkerEntrypoint's connect(socket) handles Fetcher.connect() calls and TCP listeners bound to that entrypoint.connect(socket) runs for this Worker's own service bindings to the entrypoint. A missing method fails with Handler does not export a connect() function. 1/1 pass · 1 file
Notes
Other Workers cannot connect, because cross-Worker service bindings are stubs. connect-handler-test localAddressViaServiceBinding fails because its target service is another Worker.
Tests
  • api-tests--connect-handler-test › localAddressViaServiceBinding Pass
Source
packages/runtime-node/src/bindings/service.ts:344-365
PartialWorker with a connect handler and no fetch handlerA Worker can export only connect() and serve TCP.The Worker loads. Each HTTP request fails with Handler does not export a fetch() function., as in workerd. 1 file
Notes
Orange has no inbound TCP connect() events, so the connect handler never runs.
Source
packages/runtime-node/src/runtime.ts:154-159
SupportedDurable Object fetch()stub.fetch() calls the Durable Object's fetch(request) through the input gate.stub.fetch() runs the instance fetch(request) as an ordered event inside the input gate. 1/1 pass · 2 files
Notes
A class without fetch() fails with Error Handler does not export a fetch() function. A non-Response result fails with TypeError Incorrect type for Promise: the Promise did not resolve to 'Response'. Both match workerd.
Tests
  • api-tests--actor-stub-test › main Pass
Source
packages/runtime-node/src/bindings/durable-objects/fetch.ts:128-207src/runtime/durable-object-rpc-fetch.test.ts
SupportedDurable Object alarm()alarm(alarmInfo) runs at the time from setAlarm(), with retries on failure.Runs alarm({ retryCount, isRetry, scheduledTime }) at the stored time, with up to 6 retries. 2/2 pass · 2 files
Notes
setAlarm() without an alarm() handler fails with Your Durable Object class must have an alarm() handler in order to call setAlarm(). All 17 synthetic do-alarm tests pass.
Tests
  • synthetic--do-alarm-test › throwingHandlerIsRetried Pass
  • api-tests--actor-alarms-test › test Pass
Source
packages/runtime-node/src/bindings/durable-objects/alarm-storage.ts:305-341packages/runtime-node/src/bindings/durable-objects/alarm-storage.ts:232-240
SupportedDurable Object webSocketMessage()webSocketMessage(ws, message) receives frames on WebSockets accepted with ctx.acceptWebSocket().Calls webSocketMessage(ws, message) for each frame that is not an auto-response, as an input-gated event. 2/2 pass · 1 file
Notes
A missing method silently drops the event, like workerd. The handler runs on the shared Node thread, so a synchronous loop cannot be stopped by the event timeout.
Tests
  • synthetic--do-websocket-test › clientStringDispatchedToHandler Pass
  • synthetic--do-websocket-test › clientBinaryDispatchedToHandler Pass
Source
packages/runtime-node/src/bindings/durable-objects/hibernatable-websocket-events.ts:168-181
PartialDurable Object webSocketClose()webSocketClose(ws, code, reason, wasClean) runs when a hibernatable WebSocket closes.Calls webSocketClose(ws, code, reason, wasClean) once. The socket stays listed until the handler settles. 2/3 pass · 4 files
Notes
A client's close code can be lost in the Rivet gateway: in the recorded lifecycle probe, a clean client close reached webSocketClose as 1001, not 1000. A missing method silently drops the event.
Tests
  • synthetic--do-websocket-hibernation-test › closeWhileHibernatedKeepsCodeAndReason AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal: | + actual - expected | Fail · Behavior differs
  • synthetic--do-websocket-test › clientCloseDispatchedToHandler Pass
  • api-tests--websocket-hibernation › test Pass
Source
packages/runtime-node/src/bindings/durable-objects/hibernatable-websocket-events.ts:138-153packages/runtime-node/src/bindings/durable-objects/websocket.ts:276-288packages/cloudflare-conformance/probes/lifecycle/scenario.ts:90-94packages/cloudflare-conformance/probes/lifecycle/result.json:87-91
SupportedDurable Object webSocketError()webSocketError(ws, error) runs when a hibernatable WebSocket fails.Calls webSocketError(ws, error) once and releases the socket. 1 file
Notes
No conformance test triggers a WebSocket error.
Not verified by a test
No test drives the error path. The claim is read from code.
Source
packages/runtime-node/src/bindings/durable-objects/hibernatable-websocket-events.ts:154-166
StubDurable Object connect()stub.connect() opens a TCP-style socket to the Durable Object's connect() handler.stub.connect() throws DurableObjectStub.connect is not implemented by OpenOrange. 1 file
Notes
A connect() method on a Durable Object class never runs.
Not verified by a test
Whether Cloudflare production exposes Durable Object connect() is not checked.
Source
packages/runtime-node/src/bindings/durable-objects/namespace.ts:362-369

Durable Objects

SupportedPlain class Durable ObjectsA class that does not extend DurableObject works for fetch(), alarms, and WebSockets. RPC to it fails unless js_rpc is set.Same. RPC to a plain class fails with workerd's message: The receiving Durable Object does not support RPC, because its class was not declared with extends DurableObject. 1/1 pass · 2 files
Notes
Orange ignores the js_rpc flag, so a plain class never accepts RPC.
Tests
  • api-tests--js-rpc-test › actorWithoutExtendsRejectsRpc Pass
Source
packages/runtime-node/src/bindings/durable-objects/classes.ts:13-23packages/runtime-node/src/bindings/durable-objects/rpc/methods.ts:80-87
SupportedDurableObject base classimport { DurableObject } from "cloudflare:workers". The constructor stores ctx and env, and the class enables RPC.Same. The base class sets this.ctx and this.env and brands the prototype for RPC. 1/1 pass · 1 file
Notes
None.
Tests
  • api-tests--js-rpc-test › canUseGetPutDelete Pass
Source
packages/runtime-node/src/modules/cloudflare-workers/durable-object.ts:220-254
SupportedObject constructorThe class constructor runs once per object instance, with ctx and env, before the first event.Same. Each Rivet actor generation constructs exactly one instance, with a fresh ctx and env, before any event runs. 3 files
PartialIdle eviction and sleepAn idle object is evicted from memory after some time without events. Its storage stays.An idle object sleeps after 10 seconds without events (Rivet sleepTimeout 10_000). The next event constructs a new instance. 1 file
Notes
Orange uses workerd's 10 second hibernation cadence for every idle object. Code that keeps state in instance fields loses it sooner than on Cloudflare.
Not verified by a test
Cloudflare's exact production eviction delay is not measured here.
Source
packages/runtime-node/src/bindings/durable-objects/registry.ts:428-444 Cloudflare docs
Supportednamespace.idFromName()Returns a deterministic DurableObjectId for a name. The id has a name property.Same. The id is deterministic within one deployment and class. The id bytes differ from Cloudflare's. 2/2 pass · 1 file
Notes
Ids are local to Orange and are not interchangeable with Cloudflare ids.
Tests
  • api-tests--actor-stub-test › main Pass
  • synthetic--do-id-test › idEqualityIgnoresName Pass
Source
packages/runtime-node/src/bindings/durable-objects/id.ts:270-289
Supportednamespace.idFromString()Parses a 64-digit hex id. It rejects malformed ids and ids from another class. The name is not restored.Same. It validates the hex form, the class namespace, and the jurisdiction, and drops the name. 2/2 pass · 1 file
Notes
None.
Tests
  • synthetic--do-id-test › idFromStringValidatesInput Pass
  • api-tests--actor-stub-test › main Pass
Source
packages/runtime-node/src/bindings/durable-objects/id.ts:295-315
Supportednamespace.newUniqueId()Returns a random id. The jurisdiction option restricts the id to a jurisdiction.Same. Ids use cryptographic randomness. The jurisdiction option is validated and stored on the id. 1/1 pass · 2 files
Notes
A jurisdiction is metadata only. Orange stores all data on the local host.
Tests
  • api-tests--actor-stub-test › main Pass
Source
packages/runtime-node/src/bindings/durable-objects/id.ts:319-334packages/runtime-node/src/bindings/durable-objects/namespace.ts:442-447
Supportednamespace.get()Returns a stub for an id. Options locationHint and routingMode are accepted.Same. The stub is lazy and does not contact the actor until the first call. Invalid options throw TypeError. 1/1 pass · 1 file
Notes
locationHint has no effect. See do-location-hint.
Tests
  • api-tests--actor-stub-test › main Pass
Source
packages/runtime-node/src/bindings/durable-objects/namespace.ts:402-418
Supportednamespace.getByName()Returns a stub for idFromName(name) in one call.Same. 1/1 pass · 1 file
Notes
None.
Tests
  • synthetic--do-alarm-test › idNameVisibleInAlarm Pass
Source
packages/runtime-node/src/bindings/durable-objects/namespace.ts:424-426
Supportednamespace.jurisdiction()Returns a namespace whose ids are restricted to one jurisdiction. null means no restriction.Same. A restricted namespace rejects ids from another jurisdiction. null acts like no jurisdiction. 1/1 pass · 1 file
Notes
A jurisdiction is metadata only. Orange stores all data on the local host.
Tests
  • api-tests--actor-stub-test › main Pass
Source
packages/runtime-node/src/bindings/durable-objects/namespace.ts:433-441
Supportedid.toString()Returns the id as 64 lowercase hex digits.Same format. 1/1 pass · 1 file
Notes
The digits differ from Cloudflare's for the same name.
Tests
  • api-tests--actor-stub-test › main Pass
Source
packages/runtime-node/src/bindings/durable-objects/id.ts:54-60
Supportedid.equals()Compares two ids by value. The name does not matter.Same. 1/1 pass · 1 file
Notes
None.
Tests
  • synthetic--do-id-test › idEqualityIgnoresName Pass
Source
packages/runtime-node/src/bindings/durable-objects/id.ts:44-52
Supportedid.name and ctx.id.nameid.name is the name passed to idFromName(). ctx.id.name keeps it inside the object, also in alarms after eviction.Same. Orange keeps the name in the actor's SQLite, so it survives sleep, alarm wake-ups, and deleteAll(). 1/1 pass · 1 file
Notes
None.
Tests
  • synthetic--do-alarm-test › idNameVisibleInAlarm Pass
Source
packages/runtime-node/src/bindings/durable-objects/registry.ts:521-538
Supportedid.jurisdictionThe jurisdiction of the id, or undefined.Same. idFromString() restores it. 1/1 pass · 1 file
Notes
None.
Tests
  • api-tests--actor-stub-test › main Pass
Source
packages/runtime-node/src/bindings/durable-objects/id.ts:39
Supportedstub.idThe stub's Durable Object id. id and name are the only own enumerable keys.Same. 1/1 pass · 1 file
Notes
None.
Tests
  • api-tests--actor-stub-test › main Pass
Source
packages/runtime-node/src/bindings/durable-objects/namespace.ts:216-225
Supportedstub.nameThe name the stub was made from, for getByName() and idFromName() stubs.Same. 1/1 pass · 1 file
Notes
None.
Tests
  • api-tests--actor-stub-test › main Pass
Source
packages/runtime-node/src/bindings/durable-objects/namespace.ts:216-225
Supportedstub.fetch()Sends an HTTP request to the object's fetch() handler. WebSocket upgrades work.Same, through a private Rivet route. The method, headers, and cf of the request, and the headers and status text of the object's response, cross in private heads. Gateway headers and CORS never reach the Worker, and OPTIONS reaches the object. 2/2 pass · 3 files
Notes
RivetKit's gateway client reads the whole request body into memory before it forwards it. Client-sent private head headers are dropped at the inbound edge.
Tests
  • api-tests--actor-stub-test › main Pass
  • api-tests--js-rpc-test › namedActorBinding Pass
Source
packages/runtime-node/src/bindings/durable-objects/transport-head.ts:1-149packages/runtime-node/src/bindings/durable-objects/fetch.tssrc/runtime/durable-object-fetch-boundary.test.ts:119-185
PartialStub RPC method callsstub.method(args) calls a public method of the class. Arguments and results use the RPC serializer, including stubs, functions, streams, Request, and Response.Same API, over Cap'n Web through Rivet. Calls keep E-order per stub. Errors keep name, message, and custom properties. 4/4 pass · 4 files
Notes
Values follow workerd's RPC serializer, including Blob, Response.error(), DOMException, and boxed primitives. File, FormData, URL, AbortSignal, and other classes fail with workerd's DataCloneError message. Durable Object stubs cannot be sent over RPC (see do-stub-transfer-over-rpc). An error that the object throws rejects only that call; see do-stub-broken-after-error. Calls run on the single Node thread.
Tests
  • api-tests--js-rpc-test › canUseGetPutDelete Pass
  • api-tests--js-rpc-test › eOrderTest Pass
  • api-tests--js-rpc-test › testDurableObjectExceptionProperties Pass
  • api-tests--actor-stub-test › main Pass
Source
packages/runtime-node/src/bindings/durable-objects/rpc/methods.ts:120-204packages/runtime-node/src/bindings/durable-objects/rpc/codec.ts:109-127packages/runtime-node/src/bindings/durable-objects/rpc/codec.ts:436-447tests/durable-object-rpc-values.test.ts:13-67
SupportedStub RPC property accessAwaiting stub.prop reads a property or getter of the class over RPC.Same. Own instance properties are rejected, as on Cloudflare. 1/1 pass · 1 file
Notes
Reading the property does not wake the object. Awaiting it does.
Not verified by a test
namedActorBinding is the closest saved test. No saved test reads a getter on a Durable Object stub directly.
Tests
  • api-tests--js-rpc-test › namedActorBinding Pass
Source
packages/runtime-node/src/bindings/durable-objects/rpc/methods.ts:132-136
PartialRpcPromise pipeliningCalls on an unresolved RpcPromise (stub.a().b()) are pipelined in one round trip.The result is correct, but each pipelined call waits for its parent result and then sends a new call. 2/2 pass · 1 file
Notes
Extra round trips per pipelined step. map() and onRpcBroken() on the promise read as undefined.
Tests
  • api-tests--js-rpc-test › promisePipelining Pass
  • api-tests--js-rpc-test › promisePipeliningProxy Pass
Source
packages/runtime-node/src/bindings/durable-objects/rpc/promise.ts:278-310
Stubstub.connect()Opens a TCP-style socket to the object's connect() handler.Calling it throws DurableObjectStub.connect is not implemented by OpenOrange. 1 file
Notes
Service binding connect() works. Only Durable Object stubs lack it.
Source
packages/runtime-node/src/bindings/durable-objects/namespace.ts:363-370
PartialStub reuse across requestsA stub belongs to the request that created it. Using it from another request throws Cannot perform I/O on behalf of a different request.A stub has no request owner. A stub kept in a global works from any later request. 2 files
Notes
Code that works on Orange can fail on Cloudflare. Service binding RPC objects do enforce request ownership.
Not verified by a test
Found by code reading. No saved test covers a Durable Object stub used from a second request.
Source
packages/runtime-node/src/bindings/durable-objects/namespace.ts:351-385packages/runtime-node/src/rpc/loopback.ts:55-62 Cloudflare docs
UnsupportedSending a Durable Object stub over RPCA stub can be an RPC argument or result. It arrives as a service stub (Fetcher).Fails with DataCloneError Could not serialize object of type "LazyDurableObjectStub". This type does not support serialization. 0/1 pass · 1 file
Notes
Pass the id string and call get() on the other side.
Workaround
Send id.toString() and rebuild the stub with namespace.idFromString() and get().
Tests
  • api-tests--persistent-stubs-test › storingCtxExportsActorStubWorks DataCloneError: Could not serialize object of type "LazyDurableObjectStub". This type does not support serialization. Fail · Behavior differs
Source
packages/runtime-node/src/bindings/durable-objects/rpc/codec.ts:436-447
SupportedStub broken after a failed callAfter a call through a stub fails because the object reset, later calls on that stub fail with the same error.Same. A reset or a transport failure poisons the stub's ordering lane, and the error carries durableObjectReset: true after a reset. An error that the object's own code throws rejects only that call, as in workerd. get() returns a new working stub. 1/1 pass · 2 files
PartialInput gateWhile a storage call or critical section runs, no other event reaches the object. This includes new requests and I/O results for events already running.New events (fetch, RPC, alarms, WebSocket events) wait while a critical section holds the gate. Storage calls finish synchronously, so they never open a gap. 2/2 pass · 3 files
Notes
Orange gates only event admission. A fetch() result or timer of an event that is already running can resume during another event's critical section. During an open storage.transaction(), such code that calls synchronous storage throws Synchronous storage cannot run while another event's storage.transaction() is open.
Not verified by a test
The resume-during-critical-section gap is found by code reading. No saved test covers it.
Tests
  • synthetic--do-input-gate-test › storageAwaitHoldsInputGate Pass
  • synthetic--do-input-gate-test › criticalSectionBlocksOtherCalls Pass
Source
packages/runtime-node/src/bindings/durable-objects/gates.ts:429-490packages/runtime-node/src/bindings/durable-objects/state.ts:247-254packages/runtime-node/src/bindings/durable-objects/storage.ts:937-941
SupportedOutput gate: event results and errorsA response, RPC result, or thrown error leaves the object only after the writes made before it are durable.Same. Each event waits for the output gate before its result or error is returned. If the commit fails, the object resets and the caller gets the reset error. 2 files
SupportedOutput gate: outbound fetch()A fetch() from the object is sent only after earlier writes are durable.Same. Global fetch() waits on the object's output gate before it sends. 2 files
Notes
Tested end to end with the Rivet engine stopped between the write and the fetch.
Source
packages/runtime-node/src/globals/http.ts:832-835src/runtime/durable-object-output-gate.test.ts:244
SupportedOutput gate: service binding callsA service binding fetch() or RPC call from the object leaves after earlier writes are durable.Same. Service fetch(), RPC, and connect() wait on the output gate. 3 files
Notes
The callee entrypoint is constructed before the gate opens. It runs only after it opens.
Source
packages/runtime-node/src/bindings/service.ts:461-468packages/runtime-node/src/rpc/loopback.ts:302-305src/runtime/durable-object-output-gate.test.ts:244
SupportedOutput gate: Durable Object stub callsA fetch() or RPC call through another object's stub leaves after earlier writes are durable.Same. Stub calls wait on the output gate and keep E-order. 1 file
Notes
Verified by code. The end-to-end output gate test covers service RPC, not stub calls.
Source
packages/runtime-node/src/bindings/durable-objects/ordering.ts:75-85
SupportedOutput gate: RPC session framesResults of calls on stubs or targets that an object returned are outputs of that object and wait for its writes.Same. The object side and the caller side of the private RPC WebSocket hold each outgoing frame on the output gate, in order. 3 files
SupportedOutput gate: WebSocket send()Each ws.send() from the object leaves after the writes made before it are durable, in send order.Same for WebSocketPair sockets and outbound WebSocket clients. A failed commit drops the held frame and every later one. 4 files
SupportedOutput gate: WebSocket close()ws.close() from the object waits for earlier writes, after earlier frames.Same. close() goes through the same ordered output queue as send(). 2 files
Notes
Verified by code. The end-to-end test covers send(), not close().
Source
packages/runtime-node/src/globals/websocket.ts:690packages/runtime-node/src/globals/websocket.ts:84-88
SupportedOutput gate: allowUnconfirmed writesA write with allowUnconfirmed: true does not hold outgoing messages.Same for put(), delete(), setAlarm(), and deleteAlarm(). deleteAll() ignores the option, as in workerd. 3 files
UnsupportedOutput gate gap: streamed body chunksResponse and request body chunks that stream after the headers also wait for earlier writes.Only the start of the request or response waits. Chunks written to the body stream later leave at once. 2 files
Notes
A peer can see a chunk that depends on a write that is later lost in a crash.
Not verified by a test
Found by code reading: no output gate wait in the body stream path. No test covers it.
Source
packages/runtime-node/src/globals/http.ts:832-835packages/runtime-node/src/bindings/durable-objects/state.ts:260-271
UnsupportedOutput gate gap: outbound new WebSocket() setupOpening an outbound WebSocket from the object waits for earlier writes.new WebSocket(url) connects at once. Only its later send() and close() calls wait. 1 file
Notes
The handshake request can reach the peer before earlier writes are durable.
Not verified by a test
Found by code reading. No test covers it.
Source
packages/runtime-node/src/globals/websocket.ts:507-517
UnsupportedOutput gate gap: code outside the object's async contextAll output of the object waits for its writes, whatever callback runs it.Orange finds the object's gate through AsyncLocalStorage. Output from callbacks that a raw Node.js API or a Cap'n Web session runs outside that context is not held. 2 files
Notes
Output from such callbacks can leave before earlier writes are durable.
Not verified by a test
Found by code reading. No test covers it.
Source
packages/runtime-node/src/internal/output-gate.ts:16-19packages/runtime-node/src/internal/output-gate.ts:37-39
Supportedctx.blockConcurrencyWhile()Runs a callback while no other event reaches the object. A failure or a 30 second timeout resets the object.Same, in the constructor and later. Nesting has no limit. A constructor-time block times out after 30 seconds. 3/4 pass · 2 files
Notes
The 30 second timeout applies to every call, as on workerd.
Tests
  • synthetic--do-input-gate-test › deeplyNestedCriticalSections Pass
  • synthetic--do-input-gate-test › throwingCriticalSectionBreaksObject Pass
  • synthetic--do-input-gate-test › nestedCriticalSections Pass
  • api-tests--actor-block-concurrency-depth-test › main AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: | | false !== true quota
Source
packages/runtime-node/src/bindings/durable-objects/state.ts:171-198packages/runtime-node/src/bindings/durable-objects/state.ts:40-43
Supportedctx.idThe object's DurableObjectId.Same. It is rebuilt from the Rivet actor key and stays stable across sleep. 1/1 pass · 2 files
Supportedctx.storageThe object's storage API, backed by SQLite for new_sqlite_classes.Same. Rivet's per-actor SQLite database backs it. Unknown members throw DurableObjectStorage.<name> is not implemented. 2 files
Supportedctx.waitUntil()Keeps the object alive until the promise settles.Same. Orange passes the promise to Rivet's waitUntil, which keeps the actor awake. 3 files
Partialctx.abort()Resets the object: uncommitted writes are discarded, the current event fails, and the next event gets a new instance. Alarms retry unless retryAlarm is false.Same outcome. Orange rolls back the open turn, breaks the output gate, and restarts the whole Rivet actor from durable storage. retryAlarm is honored. 2/2 pass · 3 files
Notes
The reset is a full Rivet actor restart, which is heavier than workerd's in-isolate reset.
Not verified by a test
What a reset does to open WebSocket connections on Orange is not tested.
Tests
  • synthetic--do-alarm-test › abortWithoutRetryClearsAlarm Pass
  • synthetic--do-alarm-test › alarmSetAfterAbortSurvivesAbandon Pass
Source
packages/runtime-node/src/bindings/durable-objects/state.ts:213-230packages/runtime-node/src/bindings/durable-objects/state.ts:307-330packages/runtime-node/src/bindings/durable-objects/registry.ts:323-331
Supportedctx.acceptWebSocket()Accepts a WebSocketPair server socket for hibernation, with optional tags.Same. It rejects sockets already accepted with accept(). 2/2 pass · 2 files
Notes
See limit-hibernatable-websockets and limit-websocket-tags for limits.
Tests
  • synthetic--do-websocket-test › acceptedWebSocketIsListed Pass
  • api-tests--websocket-hibernation › test Pass
Source
packages/runtime-node/src/bindings/durable-objects/state.ts:419-425packages/runtime-node/src/bindings/durable-objects/hibernatable-websockets.ts:148-156
Partialctx.getWebSockets()Returns accepted hibernatable sockets, optionally filtered by tag. It includes sockets restored after hibernation.Same. A socket stays listed during its webSocketClose. A socket the client closed while the instance was dropped is dropped after webSocketClose runs in the new instance. 4/5 pass · 3 files
Notes
A client's close code can be lost in the Rivet gateway: in the recorded lifecycle probe, a clean client close reached webSocketClose as 1001, not 1000.
Tests
  • synthetic--do-websocket-hibernation-test › closedSocketIsNotRestoredAfterHibernation Pass
  • synthetic--do-websocket-hibernation-test › socketsClosedWhileHibernatedAreDropped Pass
  • synthetic--do-websocket-hibernation-test › closeWhileHibernatedKeepsCodeAndReason AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal: | + actual - expected | Fail · Behavior differs
  • synthetic--do-websocket-test › taggedWebSocketsAddressedIndependently Pass
  • synthetic--do-websocket-test › acceptedWebSocketIsListed Pass
Source
packages/runtime-node/src/bindings/durable-objects/hibernatable-websockets.ts:345-352packages/cloudflare-conformance/probes/lifecycle/scenario.ts:90-94packages/cloudflare-conformance/probes/lifecycle/result.json:87-91
Supportedctx.getTags()Returns the tags of an accepted socket.Same. It returns a copy and throws for sockets that are not registered. 1/1 pass · 1 file
Notes
None.
Tests
  • synthetic--do-websocket-test › taggedWebSocketsAddressedIndependently Pass
Source
packages/runtime-node/src/bindings/durable-objects/hibernatable-websockets.ts:354-364
Supportedctx.setWebSocketAutoResponse()Sets one request and response pair. A matching text frame gets the response without waking the object.Same matching and response. The actor's socket host answers a matching text frame without building an instance or restarting the idle timer, also while the instance is dropped. 3/3 pass · 4 files
Notes
The handler is not called for a matching frame, as on Cloudflare. Binary frames never match.
Tests
  • synthetic--do-websocket-test › autoResponseNotDispatchedToHandler Pass
  • synthetic--do-websocket-test › autoResponseInterleavedWithDoSends Pass
  • synthetic--do-websocket-test › autoResponseSkippedAfterClose Pass
Source
packages/runtime-node/src/bindings/durable-objects/hibernatable-websockets.ts:270-290packages/runtime-node/src/bindings/durable-objects/accepted-websocket-host.ts:118-135packages/runtime-node/src/bindings/durable-objects/accepted-websocket-host.ts:272-282tests/accepted-websockets.test.ts:146-210
Supportedctx.getWebSocketAutoResponse()Returns the current auto-response pair, or null.Same. It returns a new pair object each time. 2 files
Supportedctx.getWebSocketAutoResponseTimestamp()Returns when the socket last got an automatic response, or null.Same. The timestamp survives hibernation. 2 files
Partialctx.setHibernatableWebSocketEventTimeout()Sets the maximum run time of a webSocketMessage, webSocketClose, or webSocketError handler, up to 7 days.Same limit and storage. A timeout makes Rivet sleep the object. 2 files
Supportedctx.getHibernatableWebSocketEventTimeout()Returns the event timeout, or null.Same. 1 file
Supportedctx.exports in a Durable ObjectLoopback bindings to the Worker's exported entrypoints and classes.Returns the Worker's ctx.exports, the same object as import { exports } from "cloudflare:workers". 4 files
Partialctx.props in a Durable ObjectProps passed by the caller of a ctx.exports or service binding.A facet whose class came from ctx.exports.<Name>({ props }) sees those props. Every other object sees {}, as in workerd. 1/1 pass · 2 files
Notes
A namespace in ctx.exports is not callable yet, so ctx.exports.<Name>({ props }) works only for a class without a namespace binding. tests/durable-object-facet-props.test.ts compares the facet cases with workerd 1.20260903.1.
Tests
  • api-tests--ctx-props-test › ctx-props-test-disabled Pass
Source
packages/runtime-node/src/bindings/durable-objects/state.ts:146-149packages/runtime-node/src/bindings/durable-objects/durable-object-class.ts:27-37
Partialctx.containerControls the container attached to the object.Classes listed under wrangler containers get a Container that runs one sandbox per object on ORANGE_SANDBOX_PROVIDER. start(), exec(), monitor(), destroy(), signal(), and getTcpPort().fetch() work. Other classes throw NotSupportedError. 5 files
Notes
Only Cloudflare Sandbox images run; other images and start({ entrypoint }) throw. exec({ pty }), exec({ stdin }), interceptOutboundHttp(), interceptAllOutboundHttp(), interceptOutboundHttps(), snapshotContainer(), and inspect() throw. setInactivityTimeout() is a no-op. See docs/modules/sandbox.mdx.
Source
packages/runtime-node/src/bindings/durable-objects/state.ts:423-434packages/runtime-node/src/bindings/durable-objects/state.ts:83-87packages/runtime-node/src/modules/cloudflare-sandbox/container.ts:52-58packages/runtime-node/src/modules/cloudflare-sandbox/container.ts:104-266src/runtime/sandbox.test.ts:505-564
Partialctx.facetsStarts and manages child objects (facets) that share the parent's storage.ctx.facets.get(), abort(), delete(), and clone() work. Each facet is a child Rivet Actor with its own SQLite storage, hosted by one generic actor definition, so any exported class works without a binding or migration. A string id becomes the facet's ctx.id, as in workerd. clone() returns at once and copies one synchronous row snapshot of the source facet and its children in the background; later calls to the source and destination wait for the copy. 0/1 pass · 5 files
Notes
clone() matches workerd's facet cloning test, including restarts, and survives ctx.abort() and a crash during the copy. It copies a source inside storage.transaction() after the commit, where workerd copies the state before it, and its synchronous read blocks the runtime process (1.6 s for 100 MB). Facets nest to a depth of 4 and cannot set alarms. ctx.facets is still excluded from the generated type checks. See docs/modules/durable-objects.mdx.
Tests
  • api-tests--persistent-stubs-test › persistentFacetStubs NotSupportedError: DurableObjectState.restore is not implemented Fail · Not-implemented API
Source
packages/runtime-node/src/bindings/durable-objects/state.ts:408-411packages/runtime-node/src/bindings/durable-objects/facets.ts:577-651packages/runtime-node/src/bindings/durable-objects/facet-clone.ts:87-288src/runtime/durable-object-facet-clone.test.ts:19-161src/runtime/durable-object-facets.test.ts:86-163
Stubctx.restore() (persistent stubs)With the allow_irrevocable_stub_storage flag, restores stubs stored in storage.Reading it throws DurableObjectState.restore is not implemented. 0/2 pass · 1 file
Notes
persistent-stubs-test: 0 of 20 pass.
Tests
  • api-tests--persistent-stubs-test › implicitPersistentRpcStubs NotSupportedError: DurableObjectState.restore is not implemented Fail · Not-implemented API
  • api-tests--persistent-stubs-test › persistentRpcStubs TypeError: this.ctx.restore is not a function Fail · Behavior differs
Source
packages/runtime-node/src/bindings/durable-objects/state.ts:70-77
N/Actx.configureReadReplication()Only with the experimental replica_routing flag, which Cloudflare does not deploy.Reading it throws DurableObjectState.configureReadReplication is not implemented. 1 file
Supportedalarm() handlerstorage.setAlarm() runs the class alarm() handler at the scheduled time, at least once.Same. A Rivet durable schedule fires the handler. Only one alarm handler runs at a time per object. 4/4 pass · 1 file
Notes
The alarm row commits first, then Orange updates the Rivet schedule. Startup repairs a missing or stale schedule after a crash.
Tests
  • synthetic--do-alarm-test › getSetDelete Pass
  • synthetic--do-alarm-test › replacedAlarmFiresOnceAtCommittedTime Pass
  • synthetic--do-alarm-test › overdueAlarmRunsImmediately Pass
  • api-tests--actor-alarms-test › test Pass
Source
packages/runtime-node/src/bindings/durable-objects/alarm-storage.ts:287-342
Supportedalarm() alarmInfo argumentThe handler gets { scheduledTime, retryCount, isRetry }.Same. isRetry is true when retryCount is above 0. 1/1 pass · 1 file
Notes
None.
Tests
  • synthetic--do-alarm-test › throwingHandlerIsRetried Pass
Source
packages/runtime-node/src/bindings/durable-objects/alarm-storage.ts:313-318
SupportedAlarm retriesA handler that throws is retried with exponential backoff, up to 6 times.Same. Retries start at 2 seconds, double each time, and add up to 25% jitter. A setAlarm() or deleteAlarm() during the handler replaces the retry. 1/1 pass · 1 file
Notes
Backoff matches workerd's local alarm scheduler.
Tests
  • synthetic--do-alarm-test › throwingHandlerIsRetried Pass
Source
packages/runtime-node/src/bindings/durable-objects/alarm-storage.ts:187-201
SupportedsetAlarm() without an alarm() handlersetAlarm() throws when the class has no alarm() handler. It is allowed during the constructor.Same message: Your Durable Object class must have an alarm() handler in order to call setAlarm(). 1 file
PartialWebSocket hibernationAn object with only hibernatable sockets is evicted from memory. Sockets stay open, and the next frame wakes a new instance.Emulated inside a running Rivet Actor. After 10 seconds with no event, Orange drops the object's instance and keeps the actor and its accepted sockets open. The next message, close, or error on a socket builds a new instance, which gets the sockets with their tags, attachments, and auto-response timestamps before its constructor runs. 2/2 pass · 11 files
Notes
Rivet has paused its WebSocket hibernation, so the actor stays awake while an accepted socket is open, and it sleeps only after its last accepted socket closes and 10 more seconds pass with no event. A connected object keeps its actor, sockets, and their state in memory. An auto-response frame is answered without building an instance or restarting the idle timer. An unclaimed upgrade or an RPC result that a caller still holds keeps the instance running. The event timeout cannot stop synchronous JavaScript.
Tests
  • api-tests--websocket-hibernation › test Pass
  • synthetic--do-websocket-hibernation-test › socketsClosedWhileHibernatedAreDropped Pass
Source
packages/runtime-node/src/bindings/durable-objects/registry.ts:506-514packages/runtime-node/src/bindings/durable-objects/hibernation-lifecycle.ts:3packages/runtime-node/src/bindings/durable-objects/accepted-websocket-host.ts:181-186packages/runtime-node/src/bindings/durable-objects/accepted-websocket-host.ts:234-249packages/runtime-node/src/bindings/durable-objects/registry.ts:717-735packages/runtime-node/src/bindings/durable-objects/accepted-websocket-host.ts:154-168packages/runtime-node/src/bindings/durable-objects/registry.ts:396-398packages/runtime-node/src/bindings/durable-objects/accepted-websocket-host.ts:272-282tests/accepted-websockets.test.ts:81-122tests/accepted-websockets.test.ts:146-189tests/accepted-websockets.test.ts:285-336
Supportedws.serializeAttachment()Stores a structured-clone value with the socket that survives hibernation.Same. Values use the V8 serializer, have no size limit, and are stored in Rivet connection state. 2 files
Supportedws.deserializeAttachment()Returns the value stored with the socket, also after hibernation.Same. Reads the value from Rivet connection state. 2 files
SupportedEventSource in a Durable Objectnew EventSource() works inside an object event.Same. The constructor accepts a Durable Object event context as well as a Worker request. 1/1 pass · 1 file
Notes
Outside both, it throws NotSupportedError, as on workerd.
Not verified by a test
The saved eventsource tests run in a Worker. No saved test creates an EventSource inside a Durable Object.
Tests
  • api-tests--eventsource-test › constructorTest Pass
Source
packages/runtime-node/src/globals/eventsource.ts:41-52
PartiallocationHint optionget(id, { locationHint }) asks Cloudflare to create the object near a region.Accepted and validated. It has no effect because all objects run on the local host. 2 files
PartialJurisdictionsRestricts where an object runs and stores data, for example eu or fedramp.Validated and kept on ids and stubs. Data stays on the local host. 2 files
SupportedCritical SQLite errors reset the objectSQLITE_FULL, SQLITE_IOERR, SQLITE_NOMEM, and SQLITE_INTERRUPT break the object. Later calls throw, and the next event gets a new instance.Same codes and behavior. 4/4 pass · 2 files
Notes
SQLITE_CORRUPT is not on the critical list in workerd or Orange.
Tests
  • api-tests--sql-test › testAutoRollBackOnCriticalError Pass
  • api-tests--sql-test › testCriticalErrorOnTransactionSyncCommit Pass
  • api-tests--sql-test › testCriticalErrorOnTransactionRollback Pass
  • api-tests--sync-kv-test › testAutoRollBackOnCriticalError Pass
Source
packages/runtime-node/src/bindings/durable-objects/sqlite-errors.ts:22-33packages/runtime-node/src/bindings/durable-objects/gates.ts:384-393
SupportedDurability of acknowledged writesA write is durable before any output that follows it is visible.Same through the output gate. Rivet's whenDurable() confirms each commit. 2 files
Notes
An earlier fault-injection run lost 0 of 23 acknowledged writes when the engine was killed.
Not verified by a test
The fault-injection count was measured on an earlier RivetKit build, not the pinned 0.0.0-feat-sqlite-sync preview.
Source
packages/runtime-node/src/bindings/durable-objects/gates.ts:323-345src/runtime/durable-object-output-gate.test.ts:244
PartialKV-backed Durable Objects (new_classes)A new_classes migration creates a class with the key-value storage backend.Accepted. Classes created with new_classes are stored in SQLite like new_sqlite_classes classes. 2 files
Notes
Orange is looser than Cloudflare here: ctx.storage.sql works in these classes, where Cloudflare throws because the key-value backend has no SQL.
Source
src/config/load-wrangler.ts:961-981src/commands/dev.test.ts:499-547
Rejectedrenamed_classes migrationRenames a class and keeps its objects and data.Config load fails with Unsupported Durable Object migration fields: renamed_classes. 1 file
Rejecteddeleted_classes migrationDeletes a class and all its objects.Config load fails with Unsupported Durable Object migration fields: deleted_classes. 1 file
Rejectedtransferred_classes migrationMoves a class and its objects from another Worker.Config load fails with Unsupported Durable Object migration fields: transferred_classes. 1 file
Notes
None.
Not verified by a test
Wrangler 4.129's schema lists tag, new_classes, new_sqlite_classes, renamed_classes, and deleted_classes. Whether it passes transferred_classes through to Orange is not checked.
Source
src/config/load-wrangler.ts:953-960

Durable Object storage

Supportedstorage.get(key)Returns the value for one key, or undefined.Same. Values are stored in SQLite with the V8 serializer. A number key is converted to a string, as in workerd. 2/2 pass · 1 file
Notes
noCache is accepted and has no effect. allowConcurrency has no effect on SQLite storage, as on Cloudflare.
Tests
  • synthetic--do-storage-test › singleKeyBasics Pass
  • api-tests--actor-kv-test › main Pass
Source
packages/runtime-node/src/bindings/durable-objects/storage.ts:987-1000
Supportedstorage.get(keys[])Returns a Map of found keys in key order. The KV backend takes at most 128 keys.Same. Missing keys are left out and keys sort by UTF-8 bytes. 1/1 pass · 1 file
Notes
None.
Tests
  • synthetic--do-storage-test › multiKeyBasics Pass
Source
packages/runtime-node/src/bindings/durable-objects/storage.ts:992-998
Supportedstorage.put(key, value)Stores one structured-clone value.Same. An undefined value throws put() called with undefined value. 2/2 pass · 1 file
Notes
None.
Tests
  • synthetic--do-storage-test › singleKeyBasics Pass
  • synthetic--do-storage-test › getPutOrdering Pass
Source
packages/runtime-node/src/bindings/durable-objects/storage.ts:1031-1036
Supportedstorage.put(entries)Stores key-value pairs atomically. The KV backend takes at most 128 pairs.Same. Fields whose value is undefined are skipped, as in workerd. 2/2 pass · 1 file
Notes
None.
Tests
  • synthetic--do-storage-test › putMultipleRollbackOnError Pass
  • synthetic--do-storage-test › putMultipleInTransactions Pass
Source
packages/runtime-node/src/bindings/durable-objects/storage.ts:1045-1051
Supportedput() allowUnconfirmed optionLets outgoing messages leave before the write is durable.Same. The output gate does not wait for this write. 2 files
Partialput() noCache optionSkips the in-memory storage cache for this write.Validated and has no effect, because Orange has no storage cache. 2 files
Notes
Reads after a noCache write still go to storage, so results are the same. Only memory use differs.
Source
packages/runtime-node/src/bindings/durable-objects/storage.ts:60-78packages/runtime-node/src/bindings/durable-objects/storage.ts:956-960
Supportedstorage.delete(key)Deletes one key and returns whether it existed.Same. 1/1 pass · 1 file
Notes
None.
Tests
  • synthetic--do-storage-test › singleKeyBasics Pass
Source
packages/runtime-node/src/bindings/durable-objects/storage.ts:1063-1065
Supportedstorage.delete(keys[])Deletes keys atomically and returns how many existed. The KV backend takes at most 128 keys.Same. 2/2 pass · 1 file
Notes
None.
Tests
  • synthetic--do-storage-test › multiKeyBasics Pass
  • synthetic--do-storage-test › transactionCountedDelete Pass
Source
packages/runtime-node/src/bindings/durable-objects/storage.ts:1067-1077
Supportedstorage.list()Returns a Map of all keys in key order.Same. Writes earlier in the same turn are visible. 3/3 pass · 1 file
Notes
Orange reads the whole key table and filters in JavaScript, so a list on a large store costs more than on Cloudflare.
Tests
  • synthetic--do-storage-test › listForward Pass
  • synthetic--do-storage-test › listSeesUnflushedWrites Pass
  • synthetic--do-storage-test › sqliteKvListMatrix Pass
Source
packages/runtime-node/src/bindings/durable-objects/sync-kv.ts:235-257
Supportedlist() start optionLists keys at or after start.Same. 2/2 pass · 1 file
Notes
start and startAfter together throw TypeError.
Tests
  • synthetic--do-storage-test › listEndpointChanges Pass
  • synthetic--do-storage-test › sqliteKvListMatrix Pass
Source
packages/runtime-node/src/bindings/durable-objects/sync-kv.ts:153-155
Supportedlist() startAfter optionLists keys after startAfter.Same. 1/1 pass · 1 file
Notes
None.
Tests
  • synthetic--do-storage-test › sqliteKvListMatrix Pass
Source
packages/runtime-node/src/bindings/durable-objects/sync-kv.ts:157-160
Supportedlist() end optionLists keys before end.Same. 2/2 pass · 1 file
Notes
An inverted range returns an empty Map.
Tests
  • synthetic--do-storage-test › listConsecutiveRanges Pass
  • synthetic--do-storage-test › transactionInvertedListRange Pass
Source
packages/runtime-node/src/bindings/durable-objects/sync-kv.ts:162-164
Supportedlist() prefix optionLists keys that start with prefix.Same, compared as UTF-8 bytes. 1/1 pass · 1 file
Notes
None.
Tests
  • synthetic--do-storage-test › sqliteKvListMatrix Pass
Source
packages/runtime-node/src/bindings/durable-objects/sync-kv.ts:143-150
Supportedlist() reverse optionLists keys in descending order.Same. 1/1 pass · 1 file
Notes
None.
Tests
  • synthetic--do-storage-test › listReverse Pass
Source
packages/runtime-node/src/bindings/durable-objects/sync-kv.ts:241
Supportedlist() limit optionReturns at most limit entries. limit must be positive.Same. A limit that is not a positive integer throws List limit must be positive. 2/2 pass · 1 file
Notes
None.
Tests
  • synthetic--do-storage-test › listLimitAroundDeletedKeys Pass
  • synthetic--do-storage-test › listLimitWithUnflushedPuts Pass
Source
packages/runtime-node/src/bindings/durable-objects/sync-kv.ts:74-79
Supportedstorage.deleteAll()Deletes all keys, all SQL tables, and, from compatibility date 2026-02-24, the alarm.Same. It drops every user table, view, virtual table, and trigger, keeps Rivet's private schema, and deletes the alarm. It throws inside a transaction. Open SQL cursors are canceled. 4/4 pass · 2 files
Notes
None.
Tests
  • synthetic--do-storage-test › deleteAllWithPendingWrites Pass
  • synthetic--do-storage-test › deleteAllDuringFlushAndTwice Pass
  • synthetic--do-sql-test › resetDatabase Pass
  • api-tests--delete-all-deletes-alarm-test › test Pass
Source
packages/runtime-node/src/bindings/durable-objects/storage.ts:1080-1089packages/runtime-node/src/bindings/durable-objects/sync-kv.ts:272-302
Supportedstorage.transaction()Runs an async closure in a transaction. A throw or txn.rollback() rolls it back. Other events wait.Same. The closure runs in a critical section of the input gate. Nested calls use savepoints. A handle used after commit throws. 3/3 pass · 2 files
Notes
See do-input-gate for the gap with events that are already running.
Tests
  • synthetic--do-storage-test › transactionOverlay Pass
  • synthetic--do-storage-test › transactionReadThrough Pass
  • synthetic--do-alarm-test › transactionCommitsAndRollsBackAlarm Pass
Source
packages/runtime-node/src/bindings/durable-objects/storage.ts:1190-1195packages/runtime-node/src/bindings/durable-objects/storage.ts:1198-1241
Supportedstorage.transactionSync()Runs a sync closure as a savepoint. A throw rolls it back.Same. Nested calls use savepoints. An async transaction inside it is rejected. 3/3 pass · 1 file
Notes
None.
Tests
  • synthetic--do-storage-test › putMultipleInTransactions Pass
  • api-tests--sql-test › testCriticalErrorOnTransactionSyncCommit Pass
  • api-tests--sql-test › testCriticalErrorOnTransactionSyncRollback Pass
Source
packages/runtime-node/src/bindings/durable-objects/storage.ts:1309-1340
Supportedstorage.sync()Resolves when all earlier writes are durable.Same. It commits the open turn and waits for Rivet to confirm durability. 1/1 pass · 2 files
Supportedstorage.setAlarm()Schedules the alarm for a time. A past time runs it at once. A time <= 0 throws.Same. Alarm writes join transactions and roll back with them. 3/3 pass · 2 files
Notes
See do-alarms for scheduling details.
Tests
  • synthetic--do-alarm-test › getSetDelete Pass
  • synthetic--do-alarm-test › overdueAlarmRunsImmediately Pass
  • synthetic--do-alarm-test › transactionCommitsAndRollsBackAlarm Pass
Source
packages/runtime-node/src/bindings/durable-objects/storage.ts:1132-1136packages/runtime-node/src/bindings/durable-objects/alarm-storage.ts:39-48
Supportedstorage.getAlarm()Returns the scheduled time, or null. It is null while the alarm runs, unless the handler sets a new one.Same. 2/2 pass · 1 file
Notes
None.
Tests
  • synthetic--do-alarm-test › handlerSeesNullAndClearsAlarm Pass
  • synthetic--do-alarm-test › getSetDelete Pass
Source
packages/runtime-node/src/bindings/durable-objects/storage.ts:1119-1122
Supportedstorage.deleteAlarm()Cancels the scheduled alarm.Same. 2/2 pass · 1 file
Notes
None.
Tests
  • synthetic--do-alarm-test › deletedAlarmDoesNotFire Pass
  • api-tests--actor-alarms-delete-test › main Pass
Source
packages/runtime-node/src/bindings/durable-objects/storage.ts:1101
Supportedctx.storage.kv.get()Synchronous get of one key.Same, on the same SQLite table as the async API. 1/1 pass · 1 file
Notes
None.
Tests
  • api-tests--sync-kv-test › testAutoRollBackOnCriticalError Pass
Source
packages/runtime-node/src/bindings/durable-objects/sync-kv.ts:224-233
Supportedctx.storage.kv.put()Synchronous put of one key.Same. A value that cannot be cloned throws DataCloneError. 1/1 pass · 1 file
Notes
None.
Tests
  • api-tests--sql-test › testRollbackKvInit Pass
Source
packages/runtime-node/src/bindings/durable-objects/sync-kv.ts:259-264
Supportedctx.storage.kv.delete()Synchronous delete of one key. Returns whether it existed.Same. 1 file
Notes
None.
Not verified by a test
No saved upstream test calls kv.delete(). Orange's own sync-kv unit tests cover it.
Source
packages/runtime-node/src/bindings/durable-objects/sync-kv.ts:266-270
Partialctx.storage.kv.list()Returns a lazy iterator. A new list() call invalidates the previous iterator.Same options and invalidation rule. The matching rows are read when list() is called, not while iterating. 2 files
Notes
Large lists use more memory. Writes made after list() do not show in the iterator.
Not verified by a test
Whether workerd's iterator shows writes made after list() is not compared.
Source
packages/runtime-node/src/bindings/durable-objects/sync-kv.ts:235-257packages/runtime-node/src/bindings/durable-objects/sync-kv.ts:23
Supportedstorage.getCurrentBookmark()Returns a bookmark string for the current point in time.Same format as workerd local development. Bookmarks increase on every call and persist in the _cf_METADATA table. 1/1 pass · 2 files
Notes
Bookmarks are not interchangeable with Cloudflare's.
Tests
  • api-tests--sql-test › testSessionsAPIBookmark Pass
Source
packages/runtime-node/src/bindings/durable-objects/storage.ts:1094-1106packages/runtime-node/src/bindings/durable-objects/storage.ts:54-58
Stubstorage.getBookmarkForTime()Returns a bookmark for a past time, within the last 30 days.Reading it throws DurableObjectStorage.getBookmarkForTime is not implemented. 2 files
Stubstorage.onNextSessionRestoreBookmark()Restores the object's storage to a bookmark on the next restart.Reading it throws DurableObjectStorage.onNextSessionRestoreBookmark is not implemented. 2 files
N/Astorage.waitForBookmark()workerd exposes it only with the experimental flag. Cloudflare does not deploy it.Present. It resolves at once because one local database is always up to date. 1/1 pass · 1 file
Notes
None.
Tests
  • api-tests--sql-test › testSessionsAPIBookmark Pass
Source
packages/runtime-node/src/bindings/durable-objects/storage.ts:1112-1114 Cloudflare docs

SQL

Supportedctx.storage.sql.exec()Runs one SQL statement with ? bindings and returns a cursor.Same, through RivetKit SQLite 3.46.0. Errors end with the SQLite result code, for example no such table: x: SQLITE_ERROR. 3/4 pass · 1 file
Notes
The wrong number of bindings throws Wrong number of parameter bindings for SQL query. sql-test main fails with a RivetKit internal_error.
Not verified by a test
The cause of the sql-test main failure (RivetKit internal_error) is not diagnosed.
Tests
  • synthetic--do-sql-test › failedStatementReset Pass
  • synthetic--do-sql-test › extendedErrorCodes Pass
  • synthetic--do-sql-test › rtreeEnabled Pass
  • api-tests--sql-test › main Error: no such function: cos at offset 7: SQLITE_ERROR Fail · Behavior differs
Source
packages/runtime-node/src/bindings/durable-objects/storage.ts:609-700
SupportedSQL binding value typesNumbers, strings, null, and ArrayBuffer and views bind as themselves. Other values bind as their string form, so true binds "true". BigInt throws TypeError.Same. Typed arrays and resizable ArrayBuffers bind as blobs. 2/2 pass · 1 file
Notes
None.
Tests
  • api-tests--sql-resizable-arraybuffer-test › testResizableArrayBufferBlobBinding Pass
  • api-tests--sql-resizable-arraybuffer-test › testResizableArrayBufferViewBlobBinding Pass
Source
packages/runtime-node/src/bindings/durable-objects/storage.ts:138-160
SupportedSQL result value typesResults are number, string, null, or ArrayBuffer. A 64-bit integer outside the safe range is a lossy number, not a BigInt.Same. 1 file
Supportedcursor.toArray()Returns all remaining rows as objects.Same. 1/1 pass · 1 file
Notes
None.
Tests
  • synthetic--do-sql-test › execMulti Pass
Source
packages/runtime-node/src/bindings/durable-objects/storage.ts:543-545
Supportedcursor.one()Returns the only row. Throws when there are 0 or more than 1 rows.Same messages. 1 file
Supportedcursor.raw()Iterates rows as arrays. It shares the position with object iteration.Same. 1 file
Supportedcursor.next()Returns the next row as an iterator result.Same. 1/1 pass · 2 files
Supportedcursor[Symbol.iterator]()The cursor is an iterable of row objects.Same. 1/1 pass · 2 files
Supportedcursor.columnNamesThe result column names.Same. 2 files
Unsupportedcursor.rowsReadThe rows SQLite read, including rows scanned. It grows while you iterate.The number of rows returned. 0/2 pass · 1 file
Notes
Wrong for scans, index lookups, and aggregates. readRowCounters and largeRowCounters fail.
Workaround
Do not use rowsRead for cost estimates.
Tests
  • synthetic--do-sql-test › readRowCounters AssertionError: 0 == 1 Fail · Behavior differs
  • synthetic--do-sql-test › largeRowCounters AssertionError: 0 == 1 Fail · Behavior differs
Source
packages/runtime-node/src/bindings/durable-objects/storage.ts:444
Partialcursor.rowsWrittenThe rows SQLite wrote, including index rows and trigger writes.sqlite3_changes() for statements that start with INSERT, UPDATE, DELETE, or REPLACE. 0 otherwise. 0/2 pass · 1 file
Notes
Differs for triggers, upserts, index writes, and DDL. writeRowCounters and triggerRowCounters fail.
Tests
  • synthetic--do-sql-test › writeRowCounters AssertionError: Expected values to be loosely deep-equal: | | { Fail · Behavior differs
  • synthetic--do-sql-test › triggerRowCounters AssertionError: 1 == 2 Fail · Behavior differs
Source
packages/runtime-node/src/bindings/durable-objects/storage.ts:271-279
PartialLazy SQL cursorsexec() returns a live cursor that steps SQLite as you iterate.exec() reads all rows at once. The cursor iterates the stored rows. 1/1 pass · 2 files
Notes
Large results use more memory. Counters are final at once. deleteAll() still cancels unread cursors.
Tests
  • api-tests--sql-test › testCursorUaf Pass
Source
packages/runtime-node/src/bindings/durable-objects/storage.ts:475-477packages/runtime-node/src/bindings/durable-objects/storage.ts:511-517
PartialMulti-statement exec()Runs every statement. The cursor is for the last statement. Bindings apply to the last statement.Runs every statement, but the cursor returns rows from every statement, with rowsWritten 0. Bindings throw OpenOrange does not yet support bindings on multi-statement SQL. 3/3 pass · 2 files
Notes
SELECT then UPDATE returns the SELECT rows on Orange and none on workerd.
Tests
  • synthetic--do-sql-test › execMulti Pass
  • synthetic--do-sql-test › execMultiWithFailure Pass
  • api-tests--sql-test › testMultiStatement Pass
Source
packages/runtime-node/src/bindings/durable-objects/storage.ts:454-465packages/runtime-node/src/bindings/durable-objects/storage.ts:652-662
SupportedBEGIN, COMMIT, and SAVEPOINT in SQLexec() rejects transaction statements and points to transaction() and transactionSync().Same message, also inside multi-statement SQL. 1/1 pass · 2 files
Notes
Statements before the rejected one still run, as on workerd.
Tests
  • synthetic--do-sql-test › execMultiRejectsBeginTransaction Pass
Source
packages/runtime-node/src/bindings/durable-objects/storage.ts:281-282packages/runtime-node/src/bindings/durable-objects/storage.ts:360-414
PartialReserved _cf_ table namesSQL that names a _cf_ object fails, for example access to _cf_KV.key is prohibited.A text check blocks _cf_ and _rivet_ names with not authorized. 1/2 pass · 1 file
Notes
Access is blocked, but the message differs, and _rivet_ names are also reserved. RivetKit's 16 internal _rivet_ tables and indexes always appear in sqlite_master and cannot be read.
Tests
  • synthetic--do-sql-test › regulatorReservedNames AssertionError: The input did not match the regular expression /access to _cf_KV\.key is prohibited/. Input: | | 'Error: not authorized' Fail · Behavior differs
  • api-tests--sql-restrict-names-test › main Pass
Source
packages/runtime-node/src/bindings/durable-objects/storage.ts:284-297
UnsupportedAuthorizer in DEFAULT expressionsThe SQLite authorizer also checks functions in column DEFAULT expressions.No authorizer runs. Blocked functions in DEFAULT expressions run. 0/1 pass
Notes
Orange has no native SQLite authorizer.
Tests
  • synthetic--do-sql-test › authorizerDefaultExpressions AssertionError: Missing expected exception. Fail · Behavior differs
UnsupportedSQL function allow-listOnly allowed SQL functions run. Internal functions are blocked outside a nested parse.No allow-list. Internal functions run. 0/1 pass
Notes
internalFunctionsBlocked fails with Missing expected exception.
Tests
  • synthetic--do-sql-test › internalFunctionsBlocked AssertionError: Missing expected exception. Fail · Behavior differs
UnsupportedPRAGMA allow-listOnly allow-listed PRAGMAs run, such as table_info, foreign_keys, and optimize. Others fail with not authorized.Orange has no PRAGMA allow-list. RivetKit SQLite decides which PRAGMAs run. 1 file
Notes
A PRAGMA that Cloudflare rejects can run on Orange and change database settings.
Not verified by a test
Found by code reading. regulatorReservedNames fails before its PRAGMA and ATTACH checks run, so no saved test covers them.
Source
packages/runtime-node/src/bindings/durable-objects/storage.ts:609-634 Cloudflare docs
UnsupportedDELETE and UPDATE with LIMITDELETE ... LIMIT and UPDATE ... LIMIT work.Fails with near "LIMIT": syntax error: SQLITE_ERROR. RivetKit's SQLite build lacks the grammar rule. 0/1 pass
Notes
The compile flag alone does not help. The amalgamation must be generated with the flag.
Workaround
Use DELETE ... WHERE rowid IN (SELECT rowid ... LIMIT n).
Tests
  • synthetic--do-sql-test › deleteWithLimit Error: near "LIMIT": syntax error at offset 19: SQLITE_ERROR Fail · Behavior differs
Supportedsql.databaseSizeThe database size in bytes.Same formula as workerd: used pages times the page size. 1 file
N/Asql.ingest()workerd exposes it only with an experimental flag. Cloudflare does not deploy it.Absent. Calling it throws TypeError. 1 file
N/Asql.prepare()workerd exposes it only with an experimental flag. Cloudflare does not deploy it.Absent. Calling it throws TypeError. 1 file

Runtime APIs

Partialcaches globalThe caches global gives access to the Cache API for the zone.A CacheStorage backed by one internal Rivet Actor per cache name (SQLite), with Miniflare's freshness rules. Entries survive orange dev restarts. ORANGE_CACHE=off restores the workers.dev no-op. 1/2 pass · 1 file
Notes
One local cache, not one per data center. Several ranges get the whole body with 200. Vary is ignored for matching. The per-request call limit is not enforced. Upstream cache-test matchOperations and deleteOperations depend on workerd's mock cache backend.
Tests
  • api-tests--cache-test › matchOperations AssertionError [ERR_ASSERTION]: Should have a cache HIT Fail · Behavior differs
  • api-tests--cache-put-stream-test › concurrentClonePuts Pass
Source
packages/runtime-node/src/globals/cache.ts:1-334
Partialcaches.defaultThe default cache for the zone. match(), put(), and delete() read and write the edge cache.A Cache stored in the openorange:cache actor named default. put() validates and stores fresh responses, match() returns HIT, 304, 206, or 416 responses, and delete() returns whether a live entry was removed. 1/2 pass · 1 file
Notes
See caches.
Tests
  • api-tests--cache-test › putOperations Pass
  • api-tests--cache-test › deleteOperations AssertionError [ERR_ASSERTION]: Should return true for successful delete | | false !== true Fail · Behavior differs
Source
packages/runtime-node/src/globals/cache.ts:1-334
Partialcaches.open()Opens a named cache in the zone.Resolves to a Cache stored in the openorange:cache actor named named:<name>. A name of 1024 characters or more throws TypeError: Cache name is too long. 1/1 pass · 1 file
Notes
See caches.
Tests
  • api-tests--cache-test › headersOperations Pass
Source
packages/runtime-node/src/globals/cache.ts:1-334
PartialCache classThe Cache global is the class of caches.default and of caches opened with caches.open().Exists. new Cache() throws TypeError: Illegal constructor, as in workerd. 1 file
PartialCacheStorage classThe CacheStorage global is the class of caches.Exists. new CacheStorage() throws TypeError: Illegal constructor, as in workerd. 1 file
SupportedWorker ctx.waitUntil()Keeps the invocation alive until the promise settles, after the response is sent.Tracks each promise. The runtime drains them after the handler returns or throws. 1/1 pass · 3 files
Notes
Promises added while draining are also awaited. Orange has no 30 second post-response limit.
Not verified by a test
The missing post-response time limit is read from code, not tested.
Tests
  • api-tests--js-rpc-test › waitUntilWorks Pass
Source
packages/runtime-node/src/context.ts:105-111packages/runtime-node/src/context.ts:164-184packages/runtime-node/src/events/fetch.ts:43-60
Partialctx.passThroughOnException()Forwards the request to the origin when the Worker throws.A no-op. An exception after the call still fails the request with a 500 response. 1 file
Notes
Orange has no origin to fall back to. Local workerd with no next service also answers the exception with an error.
Source
packages/runtime-node/src/context.ts:113-115
Stubctx.cacheGives cache controls, such as ctx.cache.purge(), on cache-enabled Workers.Reading ctx.cache throws NotSupportedError ExecutionContext.cache is not implemented. 1 file
PartialWorker ctx.abort()Aborts the current invocation with a reason.Disposes the RPC stubs the invocation owns, then throws the reason, which fails the invocation. 1/1 pass · 1 file
Notes
Workerd also terminates the running JavaScript at once. Node.js cannot, so code that catches the thrown reason keeps running. Durable Object ctx.abort() is separate. js-rpc-test disposal passes.
Tests
  • api-tests--js-rpc-test › disposal Pass
Source
packages/runtime-node/src/context.ts:133-150
Partialctx.propsHolds the props that a service binding or ctx.exports call bound to the entrypoint.Holds the props of a same-Worker service binding or ctx.exports call. Top-level HTTP requests get undefined. 1/1 pass · 2 files
Notes
ctx-props-test-disabled fails: with the legacy nonclass_entrypoint_reuses_ctx_across_invocations flag, workerd returns {} and Orange returns undefined.
Not verified by a test
What Cloudflare returns for ctx.props on a top-level request without that flag is not checked.
Tests
  • api-tests--ctx-props-test › ctx-props-test-disabled Pass
Source
packages/runtime-node/src/context.ts:95-103packages/runtime-node/src/runner.ts:981
Partialctx.accessHolds Cloudflare Access identity for the request when Access protects the Worker.Always undefined, like local workerd. 1/1 pass · 1 file
Notes
Orange has no Access integration, so Access-protected routes cannot read the identity.
Tests
  • api-tests--ctx-access-test › ctxAccessPropertyExists Pass
Source
packages/runtime-node/src/context.ts:121-125
Partialctx.tracingThe user tracing API. enterSpan() is a no-op outside a traced request.ctx.tracing is a no-op tracer. Callbacks run with a span whose isTraced is false, and errors propagate. 2 files
Notes
No spans are recorded. DurableObjectState has no tracing, as in workerd.
Source
packages/runtime-node/src/modules/cloudflare-workers/tracing.ts:1-78packages/runtime-node/src/context.ts:127-131
Supportedctx.mapVirtualHost()Assigns a stable virtual host name to a Fetcher for a port. workerd exposes it under the experimental flag.Assigns a stable <id>.workers.alt:<port> host and keeps the first port per Fetcher. 3/3 pass · 1 file
Notes
Works with connect() through the mapped host.
Tests
  • api-tests--js-rpc-test › mapVirtualHostConnect Pass
  • api-tests--js-rpc-test › mapVirtualHostIdempotent Pass
  • api-tests--js-rpc-test › mapVirtualHostSerialization Pass
Source
packages/runtime-node/src/context.ts:152-161
N/Actx.versionVersion information on ctx. workerd exposes it only under the experimental enable_version_api flag.Not present. ctx.version reads undefined. 1 file
Notes
Cloudflare does not deploy experimental flags. Use the version_metadata binding instead.
Source
packages/runtime-node/src/context.ts:6-15
Supportedcloudflare:workers WorkerEntrypointBase class for default and named entrypoints. The runtime passes ctx and env to the constructor.Base class that stores ctx and env. A class default export gets a new instance for each request. 3/3 pass · 2 files
Notes
Each event method needs a handler entry. Orange dispatches fetch, connect, and RPC methods.
Tests
  • api-tests--js-rpc-test › defaultExportClass Pass
  • api-tests--js-rpc-test › extendingEntrypointClasses Pass
  • api-tests--js-rpc-test › testConstructEntrypoint Pass
Source
packages/runtime-node/src/modules/cloudflare-workers/worker-entrypoint.ts:6-39packages/runtime-node/src/runtime.ts:58-73
Supportedcloudflare:workers DurableObjectBase class for Durable Object classes. Extending it enables RPC.Base class that Orange requires for Durable Object classes and RPC. 1/1 pass · 1 file
Notes
Durable Object behavior is in the Durable Objects category.
Tests
  • api-tests--js-rpc-test › actorWithoutExtendsRejectsRpc Pass
Source
packages/runtime-node/src/modules/cloudflare-workers/durable-object.ts:220
Supportedcloudflare:workers RpcTargetMarks a class whose instances travel over RPC as stubs instead of being copied.Marks the class for both Orange RPC systems. Instances travel as stubs that expose class members only. 2/2 pass · 2 files
Notes
None.
Tests
  • api-tests--js-rpc-test › loopbackJsRpcTarget Pass
  • api-tests--js-rpc-test › proxiedRpcTarget Pass
Source
packages/runtime-node/src/bindings/durable-objects/rpc/target.ts:10-19packages/runtime-node/src/rpc/loopback.ts:183-203
Supportedcloudflare:workers RpcStubnew RpcStub(value) wraps a local object or function as a disposable RPC stub.Constructs a disposable stub with dup() and Symbol.dispose. 1/1 pass · 2 files
Notes
See the JS RPC entries for ownership and disposal.
Tests
  • api-tests--js-rpc-params-ownership-test › rpcParamsDupTarget Pass
Source
packages/runtime-node/src/rpc/loopback.ts:672-703packages/runtime-node/src/rpc/loopback.ts:777-791
Supportedcloudflare:workers RpcPromiseClass of the promise an RPC call returns. It supports pipelining.Exported for instanceof checks. RPC calls return instances. 1/1 pass · 1 file
Notes
None.
Tests
  • api-tests--js-rpc-test › serializeRpcPromiseOrProprety Pass
Source
packages/runtime-node/src/rpc/loopback.ts:777-814
Supportedcloudflare:workers RpcPropertyClass of a pipelined property read on a stub.Exported for instanceof checks. Property reads on stubs return instances. 1/1 pass · 1 file
Notes
None.
Tests
  • api-tests--js-rpc-test › serializeRpcPromiseOrProprety Pass
Source
packages/runtime-node/src/rpc/loopback.ts:792-797
Supportedcloudflare:workers ServiceStubClass of a service binding stub (Fetcher).Exported. Service stubs from bindings and ctx.exports are instances. 1/1 pass · 1 file
Notes
Only same-Worker service stubs exist in Orange.
Tests
  • api-tests--js-rpc-test › sendServiceStubOverRpc Pass
Source
packages/runtime-node/src/modules/cloudflare-workers/index.ts:3
Supportedcloudflare:workers waitUntil()Registers background work on the current invocation without ctx.Adds the promise to the current execution context. Outside a request, throws the workerd Disallowed operation called within global scope error. 1 file
Notes
None.
Not verified by a test
No upstream test calls the module-level waitUntil().
Source
packages/runtime-node/src/modules/cloudflare-workers/worker-entrypoint.ts:41-52
Supportedcloudflare:workers withEnv()Runs a function with an overridden importable env.Runs the function with the override in an AsyncLocalStorage scope, with workerd's null and non-object rules. 1 file
Notes
The importable env object itself is in the Bindings category.
Not verified by a test
importable-env-test fails at load for an unrelated KV binding, so no passing test covers withEnv().
Source
packages/runtime-node/src/modules/cloudflare-workers/env.ts:51-79
Supportedcloudflare:workers withExports()Runs a function with an overridden importable exports object.Runs the function with the override in an AsyncLocalStorage scope. 1/1 pass · 1 file
Notes
None.
Tests
  • api-tests--importable-exports-test › nullableExports Pass
Source
packages/runtime-node/src/modules/cloudflare-workers/env.ts:81-83
Supportedcloudflare:workers withEnvAndExports()Runs a function with both env and exports overridden.Nests withEnv() and withExports(). 1 file
Notes
None.
Not verified by a test
No upstream test calls it.
Source
packages/runtime-node/src/modules/cloudflare-workers/env.ts:85-91
Stubcloudflare:workers restore()Restores persistent stubs. Requires the allow_irrevocable_stub_storage flag.Exported so imports link. Calling it throws cloudflare:workers restore() is not implemented by OpenOrange. 0/1 pass · 1 file
Notes
persistent-stubs-test fails 0/20.
Tests
  • api-tests--persistent-stubs-test › persistentRpcStubs TypeError: this.ctx.restore is not a function Fail · Behavior differs
Source
packages/runtime-node/src/modules/cloudflare-workers/unimplemented.ts:1-5
Supportedcloudflare:workers WorkflowEntrypointBase class for Workflow classes.Exported as a base class that stores ctx and env. A Workflow binding constructs the class for each run of an instance and calls run(event, step). 3 files
Rejectedcloudflare:workers cacheModule-level proxy for the current request's ctx.cache.Not exported. A Worker that imports it fails at load with The requested module does not provide an export named 'cache'. 3 files
Notes
cloudflare:workers resolves to Orange's ES module, so a missing named export fails when the Worker module links. The conformance classifier matches this error.
Not verified by a test
Not run against Orange for this export. The failure follows from ES module linking.
Source
packages/runtime-node/src/modules/cloudflare-workers/index.ts:1-14src/build/rewrite-module-imports.ts:54-57packages/cloudflare-conformance/src/upstream/classify.ts:104-114
Partialcloudflare:workers tracingModule-level user tracing API.Exported. It is the same no-op tracer as ctx.tracing. 2 files
Rejectedcloudflare:workers abortIsolateAborts the isolate with a reason.Not exported. A Worker that imports it fails at load with The requested module does not provide an export named 'abortIsolate'. 3 files
Notes
cloudflare:workers resolves to Orange's ES module, so a missing named export fails when the Worker module links. The conformance classifier matches this error.
Not verified by a test
Not run against Orange for this export. The failure follows from ES module linking.
Source
packages/runtime-node/src/modules/cloudflare-workers/index.ts:1-14src/build/rewrite-module-imports.ts:54-57packages/cloudflare-conformance/src/upstream/classify.ts:104-114
Supportedcloudflare:node httpServerHandler()Makes a fetch handler that routes requests to a node:http server by port.Routes requests to node:http servers registered by port, with workerd's error text for an unknown port. 1/1 pass · 2 files
Notes
node:http server behavior is in the Node.js compat category.
Tests
  • node-tests--http-server-nodejs-test › testHttpServerHandler Pass
Source
packages/runtime-node/src/modules/cloudflare-node/index.ts:1-60src/build/rewrite-module-imports.ts:38-41
Supportedcloudflare:node handleAsNodeRequest()Sends one fetch request to a node:http server by port.Routes the request to the node:http server registered on the port, with workerd's error text for an unknown port. 1/1 pass · 2 files
Notes
node:http server behavior is in the Node.js compat category.
Tests
  • node-tests--http-server-nodejs-test › testHttpServerHandler Pass
Source
packages/runtime-node/src/modules/cloudflare-node/index.ts:1-60src/build/rewrite-module-imports.ts:38-41
Supportedcloudflare:email moduleExports EmailMessage for send_email bindings and email handlers.Exports EmailMessage with from and to, as workerd does. 3 files
Notes
Sending needs a Send Email binding with ORANGE_EMAIL_SMTP_URL set; without it, the binding's calls throw. Workers that only build messages, such as the agents SDK, load and run.
Source
packages/runtime-node/src/modules/cloudflare-email/index.ts:1-16src/build/rewrite-module-imports.ts:34-37src/commands/dev.test.ts:499-547
Supportedcloudflare:workflows moduleExports NonRetryableError for Workflows.Exports NonRetryableError, as workerd does. 4 files
Partialcloudflare:pipelines moduleExports PipelineTransformationEntrypoint for Pipelines.Exports PipelineTransformationEntrypoint as a WorkerEntrypoint subclass. 2 files
Partialcloudflare:ai moduleExports Workers AI helper types and errors.Exports the same names as workerd. The error classes work. Constructing Ai, AiGateway, AutoRAG, or ToMarkdownService throws NotSupportedError. 2 files
Notes
The ai binding works through an OpenAI-compatible provider. See binding-workers-ai.
Source
packages/runtime-node/src/modules/cloudflare-ai/index.tssrc/build/rewrite-module-imports.ts:26-29
Supportedcloudflare:vectorize moduleExports Vectorize constants such as DistanceMetric.Exports the same constants as workerd. 2 files
Supportedcloudflare:br moduleExports BrowserRendering helpers.Exports BrowserRendering, which forwards fetch() like workerd. 2 files
Notes
The Browser Rendering binding it wraps needs ORANGE_BROWSER_CDP_URL. See binding-browser-rendering.
Source
packages/runtime-node/src/modules/cloudflare-br/index.tssrc/build/rewrite-module-imports.ts:30-33
SupportedUnresolvable importsworkerd fails an unresolvable import, or a require() of a module with top-level await, only when the importing module evaluates.The bundler replaces those imports with modules that throw workerd's error text and prints a [bundle-warning] for each one. 1/2 pass · 4 files
Notes
cloudflare: imports without an Orange module are not deferred. A require() of a module with unsettled top-level await hangs instead of throwing.
Tests
  • api-tests--module-tla-nested-require-test › nestedRequireOfUnsettledModuleThrows Pass
  • api-tests--module-tla-nested-require-test › unsettledTopLevelAwaitStillThrows TimeoutError: The operation was aborted due to timeout Fail · Hangs (60s timeout)
Source
src/build/bundle-worker.ts:186-221src/build/bundle-worker.ts:223-309src/build/bundle-worker.ts:319-373src/commands/dev.ts:240-242
PartialWebAssembly module imports (.wasm)Wrangler bundles .wasm imports as WebAssembly.Module values.Imports that match a CompiledWasm rule (by default **/*.wasm and **/*.wasm?module) load as a WebAssembly.Module, as in Wrangler. 0/1 pass · 2 files
Notes
The module bytes are inlined in the bundle. Source phase imports of Wasm still fail to bundle.
Tests
  • api-tests--worker-loader-wasm-test › wasmModuleSource Build failed with 3 errors: | src/build/bundle-worker.ts:232:14: ERROR: [plugin: open-orange-module-rules] ENOENT: no such file or directory, open 'src/math.wasm' | ../../../..src/wo Fail · Bundling fails
Source
src/build/bundle-worker.ts:128-175src/commands/dev.test.ts:499-547
N/AWeb File System APIOnly behind workerd's experimental enable_web_file_system flag. Cloudflare does not deploy experimental flags.Not implemented. The upstream files are scored as Not supported. 0/1 pass · 1 file
Notes
The webfs files stay in the total as failures.
Tests
  • api-tests--webfs-test › webfsTest 🍊 open-orange v0.0.1 · by rivet.dev | | Worker api-tests--webfs-test Fail · Not supported
Source
packages/cloudflare-conformance/upstream.json:13-18
N/Anew_module_registry (unbundled modules)Opt-in flag that resolves unbundled modules as URLs at runtime.Orange always bundles the Worker. 0/1 pass · 1 file
Notes
The upstream file is scored as Not supported.
Tests
  • api-tests--new-module-registry-test › complexModuleTest Build failed with 34 errors: | error: Cannot read directory "../../../..node_modules/zebra: not a \x00 valid URL": invalid argument | error: Cannot read directory "../../../..src/z Fail · Not supported
Source
packages/cloudflare-conformance/upstream.json:13-18
N/Aworkerd:unsafe moduleworkerd:unsafe exists only in workerd test or experimental configurations.Not available. The import fails when it evaluates with No such module "workerd:unsafe". 0/1 pass · 1 file
Notes
19 tests need it and are excluded from the score.
Tests
  • api-tests--memory-cache-test › basic 🍊 open-orange v0.0.1 · by rivet.dev | | Worker api-tests--memory-cache-test infra
Source
packages/cloudflare-conformance/src/upstream/classify.ts:94-96
N/Aworkerd:unsafe-eval moduleworkerd:unsafe-eval exists only in workerd test or experimental configurations.Not available. The import fails when it evaluates with No such module "workerd:unsafe-eval". 0/1 pass · 1 file
Notes
1 test needs it and is excluded from the score.
Tests
  • api-tests--new-module-registry-workerd-modules-test › workerdModules 🍊 open-orange v0.0.1 · by rivet.dev | | Worker api-tests--new-module-registry-workerd-modules-test infra
Source
packages/cloudflare-conformance/src/upstream/classify.ts:94-96
N/Aworkerd:rtti moduleworkerd:rtti exists only in workerd test or experimental configurations.Not available. The import fails when it evaluates with No such module "workerd:rtti". 0/1 pass · 1 file
Notes
rtti-test imports it and fails at load.
Tests
  • api-tests--rtti-test › rtti-test 🍊 open-orange v0.0.1 · by rivet.dev | | Worker api-tests--rtti-test Fail · File fails at load
Source
packages/cloudflare-conformance/src/upstream/classify.ts:94-96
N/Agc() globalgc() exists only in workerd test builds.Not defined. 1 file
Notes
Tests that call gc() are excluded from the score.
Source
packages/cloudflare-conformance/src/upstream/classify.ts:94-96
PartialGlobal scope isolationEach Worker runs in its own V8 isolate. The runtime's own code does not share the global scope.Worker code and the Orange runtime share one Node.js realm. Orange installs the Cloudflare globals on that realm. 2/2 pass · 1 file
Notes
Patching a shared global, such as Promise or a Node.js built-in, also changes the runtime. global-scope-test passes 22/22.
Tests
  • api-tests--global-scope-test › mutableGlobals Pass
  • api-tests--global-scope-test › validateGlobalThis Pass
Source
packages/runtime-node/src/globals/install.ts:22-39
Partialprocess globalWith nodejs_compat, each Worker has its own workerd process object.Worker code shares the host Node.js process object with the runtime. 0/2 pass · 2 files
Notes
process.exit() stops the runtime. process-nodejs-test fails 0/24 and process-exit-test fails at load.
Not verified by a test
Why each of the 24 process-nodejs-test cases fails is not checked. They fail at file load.
Tests
  • node-tests--process-nodejs-test › processEnv local | env.DUB Variable local | env.FOO Variable local Fail · File fails at load
  • node-tests--process-exit-test › test 🍊 open-orange v0.0.1 · by rivet.dev | | Worker node-tests--process-exit-test Fail · File fails at load
Source
packages/runtime-node/src/runner.ts:912-928packages/runtime-node/src/runner.ts:1141-1153
Supportedselfself refers to the global scope.self is globalThis. 1/1 pass · 1 file
Notes
None.
Tests
  • api-tests--global-scope-test › validateGlobalThis Pass
Source
packages/runtime-node/src/globals/install.ts:11-13
StubWorkerGlobalScope classThe class of the global scope.The global is a placeholder that throws Cloudflare global WorkerGlobalScope is not implemented by OpenOrange. 2 files
Notes
globalThis instanceof WorkerGlobalScope throws instead of returning true.
Source
packages/runtime-node/src/globals/unimplemented.ts:1-12packages/runtime-node/src/globals/install.ts:11-20
Stuborigin globalThe origin global property.The global is a placeholder that throws Cloudflare global origin is not implemented by OpenOrange. 2 files
PartialGlobal addEventListener()Adds a listener on the global scope for error, unhandledrejection, and rejectionhandled events.One process-wide EventTarget method exposed as a global. 1/1 pass · 1 file
Notes
Service Worker fetch listeners do not handle requests. See the FetchEvent entry.
Tests
  • api-tests--events-test › globalIsEventTarget Pass
Source
packages/runtime-node/src/globals/global-scope.ts:89-113
PartialGlobal removeEventListener()Removes a listener from the global scope.One process-wide EventTarget method exposed as a global. 1/1 pass · 1 file
Notes
Service Worker fetch listeners do not handle requests. See the FetchEvent entry.
Tests
  • api-tests--events-test › globalIsEventTarget Pass
Source
packages/runtime-node/src/globals/global-scope.ts:89-113
PartialGlobal dispatchEvent()Dispatches an event on the global scope.One process-wide EventTarget method exposed as a global. 1/1 pass · 1 file
Notes
Service Worker fetch listeners do not handle requests. See the FetchEvent entry.
Tests
  • api-tests--events-test › globalIsEventTarget Pass
Source
packages/runtime-node/src/globals/global-scope.ts:89-113
RejectedFetchEvent and Service Worker syntaxService Worker syntax Workers handle requests with addEventListener("fetch").FetchEvent is a throwing placeholder. A Worker without a default export fails at load with Worker entrypoint must have a default object export. 2 files
Notes
Only ES module Workers run on Orange.
Workaround
Convert the Worker to ES module syntax with a default export.
Source
packages/runtime-node/src/globals/unimplemented.ts:1-12packages/runtime-node/src/runtime.ts:74-77
StubExtendableEvent classThe base class of Service Worker events. User code cannot construct it.The global is a placeholder that throws Cloudflare global ExtendableEvent is not implemented by OpenOrange. 1/1 pass · 1 file
Notes
events-test extendableEventNotConstructable passes because the placeholder throws on construct.
Tests
  • api-tests--events-test › extendableEventNotConstructable Pass
Source
packages/runtime-node/src/globals/unimplemented.ts:1-12
StubScheduledEvent classThe event class for Service Worker scheduled events.The global is a placeholder that throws Cloudflare global ScheduledEvent is not implemented by OpenOrange. 2 files
Notes
Scheduled handlers are in the Worker handlers category.
Source
packages/runtime-node/src/globals/unimplemented.ts:1-12packages/runtime-node/src/globals/install.ts:11-20
StubTailEvent classThe event class for Service Worker tail events.The global is a placeholder that throws Cloudflare global TailEvent is not implemented by OpenOrange. 2 files
StubBody classThe Body mixin class shared by Request and Response.The global is a placeholder that throws Cloudflare global Body is not implemented by OpenOrange. 2 files
Notes
Request and Response bodies work. Only the Body global is missing.
Source
packages/runtime-node/src/globals/unimplemented.ts:1-12packages/runtime-node/src/globals/install.ts:11-20
UnsupportedI/O at global scopeAsynchronous I/O, timers, and random values at module scope throw Disallowed operation called within global scope.fetch(), setTimeout(), and similar calls at module scope run. Only cloudflare:workers waitUntil() throws the workerd error. 2 files
Notes
A Worker that does I/O at module scope works on Orange and fails to deploy or load on Cloudflare.
Not verified by a test
No conformance test covers module-scope I/O on Orange. The only test, new-module-registry-test noTopLevelIo, is not supported.
Source
packages/runtime-node/src/modules/cloudflare-workers/worker-entrypoint.ts:44-52packages/runtime-node/src/globals/timers.ts:51-53
Unsupportedeval() restrictioneval() throws EvalError Code generation from strings disallowed for this context, except through the unsafe_eval binding.eval() runs at any time, like in Node.js. 1/3 pass
Notes
Code that works on Orange can fail on Cloudflare. worker-test testStartupEval and unsafe-test basics fail on this.
Tests
  • api-tests--worker-test › testStartupEval AssertionError [ERR_ASSERTION]: Missing expected exception. Fail · Behavior differs
  • api-tests--unsafe-test › basics AssertionError [ERR_ASSERTION]: Missing expected exception. Fail · Behavior differs
  • api-tests--experimental-eval-test › evalTest Pass
Unsupportednew Function() restrictionnew Function() throws EvalError Code generation from strings disallowed for this context, except through the unsafe_eval binding.new Function() runs at any time, like in Node.js. 1/3 pass
Notes
Code that works on Orange can fail on Cloudflare. worker-test testStartupEval and unsafe-test basics fail on this.
Tests
  • api-tests--worker-test › testStartupEval AssertionError [ERR_ASSERTION]: Missing expected exception. Fail · Behavior differs
  • api-tests--unsafe-test › basics AssertionError [ERR_ASSERTION]: Missing expected exception. Fail · Behavior differs
  • api-tests--experimental-eval-test › evalTest Pass
UnsupportedWebAssembly compile from bytesWebAssembly.compile(), instantiate(), and new WebAssembly.Module() from raw bytes are blocked. Workers import .wasm modules instead.The WebAssembly global is Node.js's namespace, so compiling from bytes works. 1/2 pass · 1 file
Notes
wasm-memory-discard-test fails at load because Node.js 24 V8 lacks the memory.discard opcode.
Not verified by a test
The Cloudflare restriction comes from documentation, not from a test.
Tests
  • api-tests--wasm-memory-discard-test › test 🍊 open-orange v0.0.1 · by rivet.dev | | Worker api-tests--wasm-memory-discard-test Fail · File fails at load
  • api-tests--unsafe-test › newWasmModule Pass
Source
packages/runtime-node/src/globals/webassembly.ts:143-150 Cloudflare docs
PartialDate.now() clockDate.now() advances only on I/O, so code cannot time itself. This mitigates Spectre timing attacks.Date.now() is the host clock and advances during CPU work. 1/1 pass · 1 file
Notes
Timing code that relies on a frozen clock behaves differently.
Not verified by a test
No upstream test checks a frozen clock. The claim follows from Orange not overriding Date.
Tests
  • api-tests--settimeout-test › accuracyAfterCpuWork Pass
Source
packages/runtime-node/src/globals/install.ts:22-39
Partialperformance.now()Returns the same value as Date.now(), with millisecond precision.Node.js performance.now(): high resolution, measured from process start. 1/1 pass · 2 files
Notes
Values differ from Cloudflare. Durations still work.
Tests
  • node-tests--perf-hooks-nodejs-test › testPerformanceBasicFunctionality Pass
Source
packages/runtime-node/src/globals/native.ts:245-249packages/runtime-node/src/globals/native.ts:319-326
Partialperformance.timeOriginAlways 0.Node.js process start time in epoch milliseconds. 0/1 pass · 1 file
Notes
node-tests perf-hooks testPerformanceToJSON fails.
Not verified by a test
The cause of the testPerformanceToJSON failure is not confirmed to be timeOrigin.
Tests
  • node-tests--perf-hooks-nodejs-test › testPerformanceToJSON AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: | + actual - expected | Fail · Behavior differs
Source
packages/runtime-node/src/globals/native.ts:245-249
Supportedperformance.mark()Makes a PerformanceMark. toJSON() omits detail when none was given.Node.js entry, with toJSON() patched to omit a missing detail. 1/1 pass · 1 file
Notes
None.
Tests
  • node-tests--perf-hooks-nodejs-test › testPerformanceMarkToJSON Pass
Source
packages/runtime-node/src/globals/native.ts:285-317
Supportedperformance.measure()Makes a PerformanceMeasure. toJSON() omits detail when none was given.Node.js entry, with toJSON() patched to omit a missing detail. 1/1 pass · 1 file
Notes
None.
Tests
  • node-tests--perf-hooks-nodejs-test › testPerformanceMeasureToJSON Pass
Source
packages/runtime-node/src/globals/native.ts:285-317
Partialconsoleconsole output goes to Workers Logs, wrangler tail, and Tail Workers.Node.js console. Output goes to the runtime's stdout and stderr. 1/1 pass · 3 files
Notes
Tail Workers in tail_consumers get the console.debug(), console.info(), console.log(), console.warn(), and console.error() calls of each traced event as logs.
Tests
  • api-tests--self-logger-test › test Pass
Source
packages/runtime-node/src/globals/native.ts:12packages/runtime-node/src/globals/native.ts:319-326packages/runtime-node/src/internal/tail-trace.ts:238-260
SupportedreportError()Dispatches an error event on the global scope and logs it when not prevented.Dispatches an ErrorEvent on the global target, logs when not prevented, and never throws. 2/2 pass · 1 file
Notes
None.
Tests
  • api-tests--reporterror-test › reportErrorTest Pass
  • api-tests--error-in-error-event-test › test Pass
Source
packages/runtime-node/src/globals/global-scope.ts:146-171
Supportedunhandledrejection eventThe global scope receives a PromiseRejectionEvent for an unhandled rejection.Dispatches PromiseRejectionEvent on the global target. 1/1 pass · 2 files
Notes
unhandled-rejection-test passes 8/8.
Tests
  • api-tests--global-scope-test › unhandledRejectionHandler Pass
Source
packages/runtime-node/src/globals/global-scope.ts:64-87packages/runtime-node/src/globals/global-scope.ts:498-510
Supportedrejectionhandled eventThe global scope receives a PromiseRejectionEvent when a rejection gets a late handler.Dispatches PromiseRejectionEvent on the global target. 1/1 pass · 2 files
Notes
unhandled-rejection-test passes 8/8.
Tests
  • api-tests--unhandled-rejection-test › lateHandlerTriggersRejectionhandled Pass
Source
packages/runtime-node/src/globals/global-scope.ts:64-87packages/runtime-node/src/globals/global-scope.ts:498-510
SupportedqueueMicrotask()Queues a microtask. A throwing callback is reported through reportError().Validates the callback and reports a throw through reportError(). 2/2 pass · 1 file
Notes
None.
Tests
  • api-tests--global-scope-test › queueMicrotask Pass
  • api-tests--global-scope-test › queueMicrotaskError Pass
Source
packages/runtime-node/src/globals/native.ts:267-283
PartialsetTimeout()Returns a numeric id. With nodejs_compat after 2026-02-10, returns a node:timers Timeout object. Delays clamp to 100 years. Each request has at most 10,000 active timeouts.Always returns a Timeout object that converts to its numeric id. Delays clamp. There is no limit on active timeouts. 2/3 pass · 2 files
Notes
Workers without nodejs_compat, or with an older date, get an object instead of a number.
Tests
  • api-tests--global-scope-test › timeoutClamping Pass
  • api-tests--global-scope-test › timeoutCount AssertionError [ERR_ASSERTION]: Missing expected exception. quota
  • node-tests--timers-global-override-test › testGlobalSetTimeoutReturnsObject Pass
Source
packages/runtime-node/src/globals/timers.ts:38-67packages/runtime-node/src/globals/timers.ts:89-116
PartialsetInterval()Returns a numeric id. With nodejs_compat after 2026-02-10, returns a node:timers Timeout object.Always returns a Timeout object that converts to its numeric id. 2/3 pass · 2 files
Notes
Workers without nodejs_compat, or with an older date, get an object instead of a number.
Tests
  • api-tests--global-scope-test › timeoutClamping Pass
  • api-tests--global-scope-test › timeoutCount AssertionError [ERR_ASSERTION]: Missing expected exception. quota
  • node-tests--timers-global-override-test › testGlobalSetTimeoutReturnsObject Pass
Source
packages/runtime-node/src/globals/timers.ts:38-67packages/runtime-node/src/globals/timers.ts:89-116
SupportedclearTimeout()Cancels a timeout by id or by Timeout object.Accepts a Timeout object or a numeric id. 2/2 pass · 1 file
Notes
None.
Tests
  • node-tests--timers-global-override-test › testClearTimeoutAcceptsBothTypes Pass
  • api-tests--global-scope-test › timeoutImplicitCancel Pass
Source
packages/runtime-node/src/globals/timers.ts:118-125
SupportedclearInterval()Cancels an interval by id or by Timeout object.Accepts a Timeout object or a numeric id. 2/2 pass · 1 file
Notes
None.
Tests
  • node-tests--timers-global-override-test › testClearTimeoutAcceptsBothTypes Pass
  • api-tests--global-scope-test › timeoutImplicitCancel Pass
Source
packages/runtime-node/src/globals/timers.ts:118-125
SupportedsetImmediate() globalA global with nodejs_compat.The host Node.js global. 2/2 pass
Notes
Present even without nodejs_compat.
Tests
  • node-tests--timers-global-override-test › testGlobalSetImmediateAvailable Pass
  • node-tests--timers-global-override-test › testGlobalClearImmediate Pass
SupportedclearImmediate() globalA global with nodejs_compat.The host Node.js global. 2/2 pass
Notes
Present even without nodejs_compat.
Tests
  • node-tests--timers-global-override-test › testGlobalSetImmediateAvailable Pass
  • node-tests--timers-global-override-test › testGlobalClearImmediate Pass
Supportedscheduler.wait()Returns a promise that resolves after a delay and rejects when an optional signal aborts.Timer-backed promise with abort support. 2/2 pass · 1 file
Notes
None.
Tests
  • api-tests--scheduler-test › wait Pass
  • api-tests--scheduler-test › sequentialAbort Pass
Source
packages/runtime-node/src/globals/scheduler.ts:7-30
SupportedstructuredClone()workerd's serializer: Headers round-trip, unsupported platform objects throw DataCloneError, and errors keep own properties.Wraps Node.js structuredClone() with workerd's rules for Headers, platform objects, and errors. 3/3 pass · 1 file
Notes
structuredclone-error-serialize-test fails because its harness needs a queue handler.
Tests
  • api-tests--global-scope-test › structuredClone Pass
  • api-tests--global-scope-test › structuredCloneError Pass
  • api-tests--structuredclone-error-serialize-test › structuredclone-error-serialize-test Pass
Source
packages/runtime-node/src/globals/structured-clone.ts:8-80
Supportedatob()Base64 decode.Orange implementation with workerd's errors. 1/1 pass · 1 file
Notes
None.
Tests
  • api-tests--global-scope-test › base64 Pass
Source
packages/runtime-node/src/globals/base64.ts:17-31
Supportedbtoa()Base64 encode.Orange implementation with workerd's errors. 1/1 pass · 1 file
Notes
None.
Tests
  • api-tests--global-scope-test › base64 Pass
Source
packages/runtime-node/src/globals/base64.ts:17-31
PartialBuffer globalGlobal with nodejs_compat. workerd's Buffer.The host Node.js Buffer with patches for workerd differences. 1/1 pass · 1 file
Notes
Present even without nodejs_compat. node:buffer details are in the Node.js compat category.
Tests
  • node-tests--node-compat-v2-test › nodeJsExpectedGlobals Pass
Source
packages/runtime-node/src/globals/buffer.ts:11-70
Supportednavigator.userAgentCloudflare-Workers.Cloudflare-Workers. 2/2 pass · 1 file
Notes
None.
Tests
  • api-tests--navigator-test › testUserAgent Pass
  • api-tests--global-scope-test › navigatorUserAgent Pass
Source
packages/runtime-node/src/globals/navigator.ts:14-24
Supportednavigator.languageen, with the enable_navigator_language flag.Always en. 1/1 pass · 1 file
Notes
Present even without the flag.
Tests
  • api-tests--navigator-test › testLanguage Pass
Source
packages/runtime-node/src/globals/navigator.ts:14-24
Supportednavigator.languages["en"], with the enable_navigator_language flag.Always a frozen ["en"]. 1/1 pass · 1 file
Notes
Present even without the flag.
Tests
  • api-tests--navigator-test › testLanguages Pass
Source
packages/runtime-node/src/globals/navigator.ts:14-24
Supportednavigator.hardwareConcurrencyAlways 1.Always 1. 1/1 pass · 1 file
Notes
None.
Tests
  • api-tests--navigator-test › testHardwareConcurrency Pass
Source
packages/runtime-node/src/globals/navigator.ts:14-24
Supportednavigator.platformAn empty string.An empty string. 1 file
Notes
None.
Not verified by a test
No upstream test reads navigator.platform.
Source
packages/runtime-node/src/globals/navigator.ts:14-24
Supportednavigator.sendBeacon()Sends a POST in the background. Returns false outside a request.Sends a POST through ctx.waitUntil(). Returns false outside a request. 1/1 pass · 1 file
Notes
None.
Tests
  • api-tests--navigator-beacon-test › navigatorBeaconTest Pass
Source
packages/runtime-node/src/globals/navigator.ts:26-38
N/Anavigator.storageOnly with the experimental Web File System flag.Not present. 0/1 pass
Notes
See the Web File System API entry.
Tests
  • api-tests--webfs-test › webfsTest 🍊 open-orange v0.0.1 · by rivet.dev | | Worker api-tests--webfs-test Fail · Not supported
Partialcrypto.subtleworkerd's SubtleCrypto on BoringSSL.Node.js SubtleCrypto with workerd's argument checks and extensions. 4/4 pass · 1 file
Notes
resizable-arraybuffer-toctou-test fails 9/14: importKey, unwrapKey, sign, verify, and decrypt read resizable or detached buffers differently.
Tests
  • api-tests--crypto-extras-test › aesCounterOverflowTest Pass
  • api-tests--crypto-impl-asymmetric-test › rsaAlgTest Pass
  • api-tests--resizable-arraybuffer-toctou-test › importKeyResizableBuffer Pass
  • api-tests--resizable-arraybuffer-toctou-test › signResize Pass
Source
packages/runtime-node/src/globals/crypto.ts:494-624
SupportedMD5 in crypto.subtle.digest()workerd accepts MD5 in digest() for legacy protocols.digest() computes MD5 with node:crypto. 1 file
Notes
None.
Not verified by a test
No upstream test in the saved run digests with MD5.
Source
packages/runtime-node/src/globals/crypto.ts:513-522
SupportedNODE-ED25519 algorithmworkerd still accepts the legacy NODE-ED25519 algorithm name.Accepted and reported back on generated keys. 1/1 pass · 1 file
Notes
None.
Tests
  • api-tests--crypto-impl-asymmetric-test › eddsa_test Pass
Source
packages/runtime-node/src/globals/crypto.ts:281-317
Supportedcrypto.subtle.timingSafeEqual()Compares two buffers in constant time.Uses node:crypto timingSafeEqual(). 1/1 pass · 1 file
Notes
None.
Tests
  • api-tests--crypto-extras-test › timingSafeEqual Pass
Source
packages/runtime-node/src/globals/crypto.ts:81-86
Supportedcrypto.DigestStreamA WritableStream that computes a digest of the bytes written to it.A WritableStream over node:crypto createHash(). 1 file
Notes
None.
Not verified by a test
No upstream test in the saved run uses DigestStream.
Source
packages/runtime-node/src/globals/crypto.ts:46-79
Supportedcrypto.getRandomValues()Fills an integer typed array with random values. Requires crypto as the receiver.Node.js getRandomValues() with the receiver check. 1 file
Notes
None.
Not verified by a test
No upstream test in the saved run targets getRandomValues().
Source
packages/runtime-node/src/globals/crypto.ts:644-649
Supportedcrypto.randomUUID()Returns a random v4 UUID.Node.js randomUUID(). 1/1 pass · 1 file
Notes
None.
Tests
  • api-tests--crypto-extras-test › randomUuid Pass
Source
packages/runtime-node/src/globals/crypto.ts:650-652
SupportedCryptoKey classThe Web Crypto key class.The Node.js class. 1/1 pass · 1 file
Notes
None.
Tests
  • api-tests--crypto-extras-test › ecJwkKeyConsistencyCheck Pass
Source
packages/runtime-node/src/globals/node-web.ts:64-95
SupportedCrypto classThe class of the crypto global.The Node.js class. 1/1 pass · 1 file
Notes
None.
Tests
  • api-tests--crypto-extras-test › ecJwkKeyConsistencyCheck Pass
Source
packages/runtime-node/src/globals/node-web.ts:64-95
PartialReadableStreamworkerd's streams, with internal and JavaScript-backed streams.Node.js ReadableStream with patches for workerd's errors, tee cancel, and release semantics. 1/4 pass · 3 files
Notes
streams-js-test readableStreamDefaultTee and sizeAlgorithmCalled fail, and pipeToJsToNativeCancel fails. Across the stream test files Orange passes 259 of 272 tests.
Tests
  • api-tests--streams-test › rs Pass
  • api-tests--streams-js-test › readableStreamDefaultTee AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: | | 'he' !== 'hel' Fail · Behavior differs
  • api-tests--streams-js-test › sizeAlgorithmCalled AssertionError [ERR_ASSERTION]: The expression evaluated to a falsy value: | | ok(sizeCalled) Fail · Behavior differs
  • api-tests--pipe-streams-test › pipeToJsToNativeCancel AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: | + actual - expected | Fail · Behavior differs
Source
packages/runtime-node/src/globals/stream-compat.ts:1-4packages/runtime-node/src/globals/stream-compat.ts:272-274packages/runtime-node/src/globals/native.ts:253-265
SupportedReadableStream.from()Creates a stream from a sync or async iterable.Node.js ReadableStream.from() with workerd's cancel behavior. 2/2 pass
Notes
None.
Tests
  • api-tests--streams-test › readableStreamFromAsyncGenerator Pass
  • api-tests--streams-test › readableStreamFromCancelRejectsWhenReturnThrows Pass
PartialReadableStreamBYOBReaderBYOB reads into caller buffers, plus workerd's readAtLeast().Node.js BYOB reader with readAtLeast() mapped to read(view, { min }). 1/3 pass · 1 file
Notes
Resizable and detached buffers during a pending read fail 3 tests. byobReadAtLeastTee fails.
Tests
  • api-tests--streams-test › readAtLeastByobReader Pass
  • api-tests--byob-reader-resize-pending-read-test › ByobReaderResizePendingRead TypeError: Cannot perform ArrayBuffer.prototype.resize on a detached ArrayBuffer Fail · Behavior differs
  • api-tests--streams-r2-patterns-test › byobReadAtLeastTee AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: | | 1 !== 100 Fail · Behavior differs
Source
packages/runtime-node/src/globals/identity-transform-stream.ts:253-289
PartialReadableByteStreamControllerByte streams with byobRequest and respond().Node.js controller. 1/4 pass · 1 file
Notes
byobRequest is not null without autoAllocateChunkSize. Tee and respond edge cases in autovuln-37, autovuln-148, and streams-byte-handlePush-uaf-test fail.
Tests
  • api-tests--streams-respond-test › jsByteSource Pass
  • api-tests--streams-no-auto-allocate-test › byobRequestIsNullWithoutAutoAllocate AssertionError [ERR_ASSERTION]: byobRequest should be null when autoAllocateChunkSize is not set Fail · Behavior differs
  • api-tests--autovuln-37-test › teeInvalidatedRespondForwardsOnlyBytesWritten TypeError: Cannot read properties of null (reading 'view') Fail · Behavior differs
  • api-tests--autovuln-148-test › byobRespondPushCollectsRespondingConsumer AssertionError [ERR_ASSERTION]: expected a pending byobRequest Fail · Behavior differs
Source
packages/runtime-node/src/globals/node-web.ts:64-111
SupportedWritableStreamworkerd's WritableStream.Node.js WritableStream with workerd's lock and release semantics. 3/3 pass · 1 file
Notes
None.
Tests
  • api-tests--streams-test › globalScopeWritableStream Pass
  • api-tests--streams-test › cancelWriteOnReleaseLock Pass
  • api-tests--streams-backpressure-test › backpressurePipeChain Pass
Source
packages/runtime-node/src/globals/stream-compat.ts:222-270
SupportedTransformStreamworkerd's TransformStream.Node.js TransformStream. 2/2 pass · 1 file
Notes
transform-streams-test passes 15/15.
Tests
  • api-tests--transform-streams-test › simpleTransform Pass
  • api-tests--transform-streams-test › writeBackpressure Pass
Source
packages/runtime-node/src/globals/native.ts:258-261
SupportedIdentityTransformStreamA byte pipe with no internal buffer. Writes resolve when a reader consumes them.Orange implementation of the same pipe. 2/2 pass · 1 file
Notes
None.
Tests
  • api-tests--streams-r2-patterns-test › identityTransformStreamReadAtLeast Pass
  • api-tests--identity-transform-stream-uaf-test › regressionWriteCancelThenRead Pass
Source
packages/runtime-node/src/globals/identity-transform-stream.ts:57-226
SupportedFixedLengthStreamAn IdentityTransformStream that requires an exact byte count and sets Content-Length.Orange implementation with the expected length recorded for bodies. 1/1 pass · 1 file
Notes
None.
Tests
  • api-tests--streams-r2-patterns-test › fixedLengthStreamReadAtLeast Pass
Source
packages/runtime-node/src/globals/identity-transform-stream.ts:228-251
SupportedCompressionStreamgzip, deflate, and deflate-raw compression streams.Node.js CompressionStream. 1/1 pass · 1 file
Notes
None.
Not verified by a test
Only one upstream test covers it. Format support is not compared.
Tests
  • api-tests--pipe-write-special-buffer-test › SabViewPipeThroughCompressionStream Pass
Source
packages/runtime-node/src/globals/node-web.ts:64-93
SupportedDecompressionStreamgzip, deflate, and deflate-raw decompression streams.Node.js DecompressionStream. 1 file
Notes
None.
Not verified by a test
No upstream test in the saved run targets it.
Source
packages/runtime-node/src/globals/node-web.ts:64-98
SupportedTextEncoderStreamEncodes a stream of strings to UTF-8.Node.js TextEncoderStream. 1 file
Notes
None.
Not verified by a test
No upstream test in the saved run targets it.
Source
packages/runtime-node/src/globals/node-web.ts:64-108
SupportedTextDecoderStreamDecodes a byte stream to strings.Node.js TextDecoderStream. 1/1 pass · 1 file
Notes
None.
Tests
  • api-tests--streams-r2-patterns-test › textDecoderStreamRequest Pass
Source
packages/runtime-node/src/globals/node-web.ts:64-108
SupportedByteLengthQueuingStrategyStandard queuing strategy.Node.js class. 1/1 pass · 1 file
Notes
None.
Tests
  • api-tests--streams-js-test › hwmDefault Pass
Source
packages/runtime-node/src/globals/install.ts:16-19
SupportedCountQueuingStrategyStandard queuing strategy.Node.js class. 1/1 pass · 1 file
Notes
None.
Tests
  • api-tests--streams-js-test › highWaterMarkValidated Pass
Source
packages/runtime-node/src/globals/install.ts:16-19
SupportedTextEncoderUTF-8 encoder.Orange TextEncoder. 1/1 pass · 1 file
Notes
None.
Tests
  • api-tests--encoding-test › textEncoderTest Pass
Source
packages/runtime-node/src/globals/encoding.ts:87-103
PartialTextDecoderDecoder for UTF-8 and the legacy WHATWG encodings.Orange TextDecoder over Node.js ICU decoders. 1/3 pass · 1 file
Notes
Non-fatal ISO-2022-JP and replacement pushback cases fail 2 of 18 encoding-test cases.
Tests
  • api-tests--encoding-test › allTheDecoders Pass
  • api-tests--encoding-test › replacementPushbackAsciiCharactersLoose AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: | | '\x80' !== '�' Fail · Behavior differs
  • api-tests--encoding-test › stickyMultibyteStateIso2022JpLoose AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: | | '�' !== '�(' Fail · Behavior differs
Source
packages/runtime-node/src/globals/encoding.ts:48-86
SupportedURLWHATWG URL.Orange URL class over Node.js URL. 2/2 pass · 1 file
Notes
url-test passes 20/20.
Tests
  • api-tests--url-test › urlConstructorTests Pass
  • api-tests--url-test › urlParseStatic Pass
Source
packages/runtime-node/src/globals/url.ts:161
SupportedURLSearchParamsWHATWG URLSearchParams.Orange class over Node.js URLSearchParams. 2/2 pass · 1 file
Notes
None.
Tests
  • api-tests--url-test › wptTestURLSearchParamsConstructor Pass
  • api-tests--url-searchparams-iterator-uaf-test › entryIteratorReentrantDelete Pass
Source
packages/runtime-node/src/globals/url.ts:69
PartialURLPatternworkerd's URLPattern.Node.js URLPattern with workerd's result object shapes. 1/2 pass · 1 file
Notes
urlpattern-regex-search-oob-test fails.
Tests
  • api-tests--url-test › urlPatternBasics Pass
  • api-tests--urlpattern-regex-search-oob-test › urlpatternRegexSearchOobRegression AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: | + actual - expected | Fail · Behavior differs
Source
packages/runtime-node/src/globals/url-pattern.ts:13-38
PartialBlobworkerd's Blob.Node.js Blob with workerd's size checks. 1/2 pass · 1 file
Notes
Blob construction from a resizable ArrayBuffer does not throw TypeError (blob2-test noResizable).
Tests
  • api-tests--blob-test › test1 Pass
  • api-tests--blob2-test › noResizable AssertionError [ERR_ASSERTION]: Missing expected exception (TypeError). Fail · Behavior differs
Source
packages/runtime-node/src/globals/native.ts:253
SupportedFileworkerd's File.Node.js File with workerd's inspect output. 1/1 pass · 1 file
Notes
None.
Tests
  • api-tests--blob-test › testInspect Pass
Source
packages/runtime-node/src/globals/node-web.ts:114-131
SupportedFormDataworkerd's FormData and multipart parser.undici FormData with an Orange multipart and urlencoded parser that follows workerd. 2/3 pass · 1 file
Notes
form-data-legacy-test fails: it tests a legacy compat date where files turn into strings.
Tests
  • api-tests--form-data-test › testFormDataParser Pass
  • api-tests--form-data-test › w3cTestFormData Pass
  • api-tests--form-data-legacy-test › sendFilesInFormdata Error: expected round-trip turns into string (wrong, but backwards-compatible) Fail · Behavior differs
Source
packages/runtime-node/src/globals/form-data.ts:133-244
SupportedHeadersworkerd's Headers, including getSetCookie() and immutable headers.Orange Headers class. 2/2 pass · 1 file
Notes
None.
Tests
  • api-tests--headers-immutable-prototype-test › test Pass
  • api-tests--response-json › headers Pass
Source
packages/runtime-node/src/globals/http.ts:71-176
SupportedRequestworkerd's Request, including cf and signal.Orange Request class. 1/1 pass · 1 file
Notes
request.cf and request.signal behavior is in the Fetch category.
Tests
  • api-tests--request-clone-test › clone Pass
Source
packages/runtime-node/src/globals/http.ts:574
SupportedResponseworkerd's Response, including Response.json() and webSocket.Orange Response class. 2/2 pass · 1 file
Notes
None.
Tests
  • api-tests--response-json › basics Pass
  • api-tests--response-used-body-test › abortInternalStreamsTest Pass
Source
packages/runtime-node/src/globals/http.ts:866
SupportedAbortControllerworkerd's AbortController with its default reason text.The Node.js class with workerd's default reason. 1/2 pass · 1 file
Notes
abortsignal-test passes 38/40. The 2 failures call workerd test-only hooks.
Tests
  • api-tests--abortsignal-test › abortcontroller Pass
  • api-tests--abortsignal-test › crossRequestRegistrationChurn TypeError: moduleScopeChurnController.signal.getNativeRegistrationCountForTest is not a function Fail · Behavior differs
Source
packages/runtime-node/src/globals/abort.ts:8-50
SupportedAbortSignalworkerd's AbortSignal with its reason getter rules.The Node.js class with workerd's reason derivation. 1/2 pass · 1 file
Notes
abortsignal-test passes 38/40. The 2 failures call workerd test-only hooks.
Tests
  • api-tests--abortsignal-test › abortcontroller Pass
  • api-tests--abortsignal-test › crossRequestRegistrationChurn TypeError: moduleScopeChurnController.signal.getNativeRegistrationCountForTest is not a function Fail · Behavior differs
Source
packages/runtime-node/src/globals/abort.ts:8-50
SupportedAbortSignal.timeout()Returns a signal that aborts after a delay.Node.js AbortSignal.timeout(). 2/2 pass
Notes
None.
Tests
  • api-tests--abortsignal-test › timedAbort Pass
  • api-tests--abortsignal-test › rpcAbortSignalTimeout Pass
SupportedAbortSignal.any()Returns a signal that aborts when any input aborts.Node.js AbortSignal.any(). 2/2 pass
Notes
None.
Tests
  • api-tests--abortsignal-test › anyAbort Pass
  • api-tests--abortsignal-test › anyOfAbortedSignalAdoptsItsState Pass
SupportedEventworkerd's Event: timeStamp is 0 and returnValue is read-only.Node.js Event with workerd's dispatch phase and returnValue rules. 2/2 pass · 1 file
Notes
None.
Tests
  • api-tests--events-test › event Pass
  • api-tests--events-test › eventSubclass Pass
Source
packages/runtime-node/src/globals/event.ts:53-130
PartialEventTargetworkerd's EventTarget. It snapshots listeners per dispatch and rejects capture and passive listeners.Node.js EventTarget with workerd's snapshot and listener option rules. 2/3 pass · 1 file
Notes
Only spec-compliant dispatch exceptions exist. The legacy no_spec_compliant_dispatch_exceptions mode is not implemented, so 3 of 4 legacy-dispatch-exceptions-test cases fail.
Tests
  • api-tests--events-test › basicEventTarget Pass
  • api-tests--events-test › passiveCaptureListener Pass
  • api-tests--legacy-dispatch-exceptions-test › dispatchEventPropagates AssertionError [ERR_ASSERTION]: Missing expected exception (Error). Fail · Behavior differs
Source
packages/runtime-node/src/globals/global-scope.ts:173-223
SupportedCustomEventStandard CustomEvent.Node.js CustomEvent. 1/1 pass · 1 file
Notes
None.
Tests
  • api-tests--events-test › customEvent Pass
Source
packages/runtime-node/src/globals/node-web.ts:64-95
SupportedErrorEventThe error event for the global scope.Orange ErrorEvent class. 1/1 pass · 1 file
Notes
None.
Tests
  • api-tests--events-test › errorEventSpecInit Pass
Source
packages/runtime-node/src/globals/global-scope.ts:33-60
SupportedCloseEventThe WebSocket close event.Node.js CloseEvent. 2/2 pass · 1 file
Notes
None.
Tests
  • api-tests--events-test › closeEvent Pass
  • api-tests--events-test › closeEventSpecInit Pass
Source
packages/runtime-node/src/globals/node-web.ts:64-91
SupportedMessageChannelMakes a pair of in-process ports.Orange in-process implementation. 2/2 pass · 1 file
Notes
messageport-test passes 16/16. messageport-gc-test needs workerd:unsafe.
Tests
  • api-tests--messageport-test › simple1 Pass
  • api-tests--messageport-test › postMessageRpcTarget Pass
Source
packages/runtime-node/src/globals/messagechannel.ts:121-264
SupportedMessagePortDelivery is deferred to a microtask, and messages queue until a listener exists.Orange MessagePort with the same rules, including RpcTarget messages. 2/2 pass · 1 file
Notes
messageport-test passes 16/16. messageport-gc-test needs workerd:unsafe.
Tests
  • api-tests--messageport-test › simple1 Pass
  • api-tests--messageport-test › postMessageRpcTarget Pass
Source
packages/runtime-node/src/globals/messagechannel.ts:121-264
SupportedMessageEventMessageEvent that accepts any MessagePort-like source.Orange MessageEvent with workerd's init rules. 2/2 pass · 1 file
Notes
None.
Tests
  • api-tests--events-test › messageEventSpecInit Pass
  • api-tests--messageport-test › messageEventSourceAndPorts Pass
Source
packages/runtime-node/src/globals/messagechannel.ts:44-111
SupportedDOMExceptionStandard DOMException with DOMException.isError().Node.js DOMException with isError() added. 1/1 pass · 1 file
Notes
None.
Tests
  • api-tests--rpc-error-test › domExceptionClone Pass
Source
packages/runtime-node/src/globals/native.ts:53-63
SupportedWebSocketPairCreates two coupled WebSockets, one to return in a 101 response and one to accept().Orange in-process pair with workerd's OPEN, CLOSING, and CLOSED rules. Durable Object sends wait on the output gate. 2/2 pass · 2 files
Notes
None.
Tests
  • api-tests--global-scope-test › webSocketPairIterable Pass
  • api-tests--websocket-allow-half-open-test › halfOpenCloseKeepsClosingState Pass
Source
packages/runtime-node/src/globals/websocket.ts:502-506packages/runtime-node/src/globals/websocket.ts:784
SupportedWebSocket classworkerd's WebSocket: accept(), binaryType, and the WebSocket constructor for outbound connections.Orange WebSocket on undici's WebSocket with workerd's accept and send rules. 2/2 pass · 1 file
Notes
websocket-constructor-test passes 18/18. Outbound connection setup is not held by the Durable Object output gate.
Tests
  • api-tests--websocket-constructor-test › binaryTypeDefaultsToBlob Pass
  • api-tests--websocket-constructor-test › closeReasonTooLong Pass
Source
packages/runtime-node/src/globals/websocket.ts:507-697
SupportedWebSocketRequestResponsePairThe request and response pair for Durable Object WebSocket auto-responses.Orange class. 1/1 pass · 1 file
Notes
Auto-response behavior is in the Durable Objects category.
Tests
  • api-tests--websocket-hibernation › test Pass
Source
packages/runtime-node/src/globals/websocket.ts:767-782
PartialHTMLRewriterStreams HTML through lol-html. Stream and Response content arguments stream into the output.Uses lol-html through html-rewriter-wasm 0.4.1. Stream and Response content arguments are read fully into a string before insertion. 1/2 pass · 4 files
Notes
htmlrewriter-test passes 32/33. streamingReplacementBadUTF8 fails because the content is decoded to a string first.
Tests
  • api-tests--htmlrewriter-test › streamingReplacement Pass
  • api-tests--htmlrewriter-test › streamingReplacementBadUTF8 TypeError: Parser error: Invalid UTF-8 Fail · Behavior differs
Source
packages/runtime-node/src/globals/html-rewriter.ts:6-8packages/runtime-node/src/globals/html-rewriter.ts:62-71packages/runtime-node/src/globals/html-rewriter.ts:132-143packages/runtime-node/package.json:31
SupportedEventSourceA fetch-driven event-stream client with reconnection, plus EventSource.from(). Only inside a request or Durable Object event.Orange EventSource with workerd's rules. It works in Worker requests and in Durable Objects. 3/3 pass · 2 files
Notes
eventsource-test passes 18/18.
Tests
  • api-tests--eventsource-test › eventSourceFromTest Pass
  • api-tests--eventsource-test › reconnectFailTest Pass
  • api-tests--eventsource-gc-test › eventsource-gc-test Pass
Source
packages/runtime-node/src/globals/eventsource.ts:38-63packages/runtime-node/src/globals/eventsource.ts:102
SupportedAsyncLocalStorage.bind() across requestsA function bound in one request throws when it runs in another request.Stock Node.js AsyncLocalStorage.bind(). 1/3 pass · 1 file
Notes
Same as Cloudflare. Orange is looser than Cloudflare here: Node.js capabilities that workerd removes or stubs are available.
Tests
  • node-tests--bound-als-test › test AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: | | 200 !== 500 Fail · Behavior differs
  • api-tests--als-test › customthenable Pass
  • api-tests--als-only-test › customthenable Error: Expected an error to be thrown Fail · Behavior differs
Source
src/build/rewrite-module-imports.ts:12-21
SupportedAsyncLocalStorage.snapshot() across requestsA snapshot made in one request throws when it runs in another request.Stock Node.js AsyncLocalStorage.snapshot(). 1/3 pass · 1 file
Notes
Same as Cloudflare. Orange is looser than Cloudflare here: Node.js capabilities that workerd removes or stubs are available.
Tests
  • node-tests--bound-als-test › test AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: | | 200 !== 500 Fail · Behavior differs
  • api-tests--als-test › customthenable Pass
  • api-tests--als-only-test › customthenable Error: Expected an error to be thrown Fail · Behavior differs
Source
src/build/rewrite-module-imports.ts:12-21
PartialPromises across requestsA promise from one request can settle in another. The continuation runs in the awaiting request's context.Basic resolve, reject, stream, and thenable cases work. 1/4 pass
Notes
cyclicAwaitsWorks and expiredContextWorks hang. asyncIterWorks fails.
Tests
  • api-tests--cross-context-promise-test › crossContextResolveWorks Pass
  • api-tests--cross-context-promise-test › cyclicAwaitsWorks TimeoutError: The operation was aborted due to timeout Fail · Hangs (60s timeout)
  • api-tests--cross-context-promise-test › expiredContextWorks TimeoutError: The operation was aborted due to timeout Fail · Hangs (60s timeout)
  • api-tests--cross-context-promise-test › asyncIterWorks AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: | + actual - expected | Fail · Behavior differs
PartialJS RPC error propertiesA thrown error keeps its type, message, and own properties, gains remote: true, and keeps the remote stack in stack2.Keeps type, message, cause, and own enumerable properties, and sets remote: true. stack2 is not set. 2/3 pass · 1 file
Notes
rpc-error-test test fails on the missing stack2.
Tests
  • api-tests--js-rpc-test › testExceptionProperties Pass
  • api-tests--js-rpc-test › testDurableObjectExceptionProperties Pass
  • api-tests--rpc-error-test › test AssertionError [ERR_ASSERTION]: Expected "actual" to be strictly unequal to: | | 'Error: boom\n' + Fail · Behavior differs
Source
packages/runtime-node/src/rpc/loopback.ts:902-942
SupportedJS RPC async stack tracesA remote error gets the local stack of the awaiting code, with async frames.Captures the stack where the caller awaits the result. 1/1 pass · 1 file
Notes
None.
Tests
  • api-tests--js-rpc-test › testAsyncStackTrace Pass
Source
packages/runtime-node/src/rpc/loopback.ts:586-602
SupportedAbortSignal over JS RPCAn AbortSignal passed over RPC aborts on the receiver when the sender aborts.Mirrors the signal into a receiver copy. 2/3 pass · 1 file
Notes
rpcDestroySignalUnclean fails because it calls a workerd test-only hook.
Tests
  • api-tests--abortsignal-test › rpcAbortSignalAbort Pass
  • api-tests--abortsignal-test › rpcCrossRequestSignal Pass
  • api-tests--abortsignal-test › rpcDestroySignalUnclean TypeError: this.ac.signal.skipReleaseForTest is not a function Fail · Behavior differs
Source
packages/runtime-node/src/rpc/loopback.ts:1039-1050
SupportedJS RPC stub ownership across requestsStubs, RPC promises, and pipelined properties belong to the request that made them. Use from another request throws Cannot perform I/O on behalf of a different request.Same rule and error text. 1/1 pass · 1 file
Notes
None.
Tests
  • api-tests--js-rpc-test › crossContextSharingDoesntWork Pass
Source
packages/runtime-node/src/rpc/loopback.ts:55-73
SupportedJS RPC parameter and result ownershipWith rpc_params_dup_stubs, parameters duplicate the caller's stubs. Results transfer the callee's stubs.Same rule. Orange always applies rpc_params_dup_stubs. 2/3 pass · 1 file
Notes
sendStubOverRpc fails: it expects the older transfer rule for parameters.
Tests
  • api-tests--js-rpc-params-ownership-test › rpcParamsDontTransferOwnership Pass
  • api-tests--js-rpc-params-ownership-test › rpcReturnsTransferOwnership Pass
  • api-tests--js-rpc-test › sendStubOverRpc AssertionError [ERR_ASSERTION]: Missing expected rejection (Error). Fail · Behavior differs
Source
packages/runtime-node/src/rpc/loopback.ts:827-830
SupportedJS RPC stub disposalDisposing a stub releases it. A target's Symbol.dispose runs after its last stub is released.Same rule with reference counting across dup() copies. A service binding call disposes the callee's leftover stubs when the call ends, or when the caller disposes a result that holds stubs. 1/1 pass · 3 files
SupportedJS RPC promise pipeliningCalls on an unresolved RPC result are sent before the result arrives.Pipelined calls go to the result once it settles. 2/2 pass · 1 file
Notes
None.
Tests
  • api-tests--js-rpc-test › promisePipelining Pass
  • api-tests--js-rpc-test › promisePipeliningProxy Pass
Source
packages/runtime-node/src/rpc/loopback.ts:459-492
SupportedFunctions over JS RPCA function passed over RPC becomes a stub that calls back into the sender.Same. Calls run in the context that exported the function. 1/1 pass · 1 file
Notes
None.
Tests
  • api-tests--js-rpc-params-ownership-test › rpcParamsDupFunction Pass
Source
packages/runtime-node/src/rpc/loopback.ts:272-278
SupportedRpcTarget objects over JS RPCAn RpcTarget passed over RPC becomes a stub. Only class members are reachable.Same lookup rules, including Proxy targets. 2/2 pass · 2 files
Notes
None.
Tests
  • api-tests--js-rpc-test › proxiedRpcTarget Pass
  • api-tests--js-rpc-test › receiveStubOverRpc Pass
Source
packages/runtime-node/src/rpc/loopback.ts:183-203packages/runtime-node/src/rpc/loopback.ts:1052-1063
SupportedStreams over JS RPCReadableStream and WritableStream move to the receiver. A far-side failure shows as a disconnect error.Same. 2/2 pass · 1 file
Notes
None.
Tests
  • api-tests--js-rpc-test › streams Pass
  • api-tests--js-rpc-writable-teardown-test › runner Pass
Source
packages/runtime-node/src/rpc/loopback.ts:996-1037
SupportedSockets over JS RPCA cloudflare:sockets Socket passed over RPC transfers to the receiver.Transfers the socket. A transferred socket cannot start TLS and keeps allowHalfOpen. 3/3 pass · 3 files
Notes
None.
Tests
  • api-tests--outbound-interceptor-socket-test › interceptorForwardsSocket Pass
  • api-tests--outbound-interceptor-socket-test › transferredSocketCannotStartTls Pass
  • api-tests--outbound-interceptor-socket-test › transferringUnopenedSocketThrows Pass
Source
packages/runtime-node/src/rpc/loopback.ts:1139packages/runtime-node/src/modules/cloudflare-sockets/socket.ts:381-424packages/runtime-node/src/modules/cloudflare-sockets/socket.ts:533-537
PartialHeaders over JS RPCHeaders serialize over RPC and keep each Set-Cookie value.Headers serialize over RPC, with a difference that serializeHttpTypes reports. 1/2 pass
Notes
serializeHttpTypes fails in all four js-rpc test variants.
Not verified by a test
serializeHttpTypes fails at one strictEqual assertion. The test checks Headers, Request, and Response in sequence, and which type differs is not confirmed, so each is marked partial.
Tests
  • api-tests--js-rpc-test › serializeHttpTypes AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: | + actual - expected | Fail · Behavior differs
  • api-tests--js-rpc-test › serializeBlob Pass
PartialRequest over JS RPCA Request serializes over RPC with its method, headers, redirect, body, cf, and signal.A Request serializes over RPC, with a difference that serializeHttpTypes reports. 1/2 pass
Notes
serializeHttpTypes fails in all four js-rpc test variants.
Not verified by a test
serializeHttpTypes fails at one strictEqual assertion. The test checks Headers, Request, and Response in sequence, and which type differs is not confirmed, so each is marked partial.
Tests
  • api-tests--js-rpc-test › serializeHttpTypes AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: | + actual - expected | Fail · Behavior differs
  • api-tests--js-rpc-test › serializeBlob Pass
PartialResponse over JS RPCA Response serializes over RPC with its status, statusText, headers, body, and cf.A Response serializes over RPC, with a difference that serializeHttpTypes reports. 1/2 pass
Notes
serializeHttpTypes fails in all four js-rpc test variants.
Not verified by a test
serializeHttpTypes fails at one strictEqual assertion. The test checks Headers, Request, and Response in sequence, and which type differs is not confirmed, so each is marked partial.
Tests
  • api-tests--js-rpc-test › serializeHttpTypes AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: | + actual - expected | Fail · Behavior differs
  • api-tests--js-rpc-test › serializeBlob Pass
SupportedJS RPC pipelined property depth limitPipelined property paths have a maximum depth.No limit. A 200-level property path works. 2 files
Notes
Workerd's limit protects its native stack. Orange keeps the path in an array.
Source
packages/runtime-node/src/rpc/loopback.ts:576-577tests/beyond-cloudflare-quotas.test.ts:65-67
UnsupportedStoring RPC stubs in Durable Object storageWith allow_irrevocable_stub_storage, ctx.storage.put() accepts RPC stubs and stores them.Stubs do not serialize into storage. ctx.restore() is a separate entry. 0/3 pass
Notes
persistent-stubs-test fails 0/20 and stub-storage-test fails 0/2.
Tests
  • api-tests--persistent-stubs-test › persistentRpcStubs TypeError: this.ctx.restore is not a function Fail · Behavior differs
  • api-tests--persistent-stubs-test › storingCtxExportsActorStubWorks DataCloneError: Could not serialize object of type "LazyDurableObjectStub". This type does not support serialization. Fail · Behavior differs
  • api-tests--stub-storage-test › storeServiceBinding TypeError: Cannot serialize value: (couldn't stringify value) Fail · Behavior differs
Alternative@cloudflare/sandbox (Sandbox SDK)Runs each Sandbox Durable Object in a Container with exec, processes, files, git, sessions, code interpreter, and preview URLs.Orange replaces the package at bundle time. Each Sandbox Durable Object owns one sandbox on the ORANGE_SANDBOX_PROVIDER backend: local (default, not isolated), e2b, daytona, or freestyle. The sandbox id persists in the object storage and reconnects after restarts. 3 files
Notes
createSession, createCodeContext, and runCode throw. Preview URLs work with the local provider only. Background processes stop with orange dev. E2B, Daytona, and Freestyle are untested without API keys.
Source
packages/runtime-node/src/modules/cloudflare-sandbox/index.ts:1-30packages/runtime-node/src/modules/cloudflare-sandbox/providers.ts:1-20src/runtime/sandbox.test.ts:1-27

Fetch

PartialGlobal fetch()Subrequests leave through Cloudflare's network. Private and loopback addresses are not reachable.An Orange wrapper over undici 8 sends requests from the host, so they can reach localhost and private networks. 3/3 pass · 1 file
Notes
Inside a Durable Object, fetch() waits for the output gate before it sends. fetch-test, data URL, redirect, and abort tests pass.
Tests
  • api-tests--fetch-test › test Pass
  • api-tests--fetch-test › fetchGen Pass
  • api-tests--abortable-fetch-test › timedAbort Pass
Source
packages/runtime-node/src/globals/http.ts:825-848
Supportedredirect option (follow, manual, error)fetch() follows redirects by default, returns the 3xx response with manual, and rejects with error.Passes redirect to undici, which applies follow, manual, and error. Other values throw Invalid redirect value. 2/2 pass · 2 files
Notes
Cross-origin redirects drop Authorization. Service binding fetch() follows redirects inside the Worker with the same rules.
Not verified by a test
The rejection message for redirect: "error" is not compared with workerd.
Tests
  • api-tests--fetch-redirect-test › crossOriginRedirectStripsAuthorization Pass
  • api-tests--fetch-redirect-test › sameOriginRedirectPreservesAuthorization Pass
Source
packages/runtime-node/src/globals/http.ts:486-496packages/runtime-node/src/bindings/service.ts:374-438
PartialIncoming request.cfrequest.cf holds colo, country, ASN, TLS, and bot management data.Every inbound request gets Miniflare's placeholder request.cf (colo DFW, country US, Austin) with httpProtocol from the request. 4 files
Notes
The values are fixed, so geolocation and bot fields do not describe the real client. wrangler dev downloads real values for the developer's location when it can. The same request.cf reaches Durable Object fetch() and WebSocket upgrades.
Workaround
Read request.cf with optional chaining and a default.
Source
packages/runtime-node/src/events/inbound-cf.ts:1-65packages/runtime-node/src/runner.ts:960-965src/commands/dev.test.ts:499-547src/runtime/durable-object-fetch-boundary.test.ts:119-147
SupportedCF-Connecting-IP inbound headerInbound requests carry CF-Connecting-IP with the client IP.Set to the client socket address unless the request already has the header, as in Miniflare. 3 files
UnsupportedCF-Ray inbound headerInbound requests carry CF-Ray with the request id.Not added. The request carries only the headers the client sent. 1 file
Notes
Code that logs CF-Ray gets null.
Source
packages/runtime-node/src/runner.ts:278-297
UnsupportedCF-IPCountry inbound headerInbound requests carry CF-IPCountry with the client country.Not added. The request carries only the headers the client sent. 1 file
Notes
Code that reads CF-IPCountry gets null.
Source
packages/runtime-node/src/runner.ts:278-297
UnsupportedX-Forwarded-Proto inbound headerInbound requests carry X-Forwarded-Proto with the client protocol.Not added. The request carries only the headers the client sent. 1 file
Notes
Code that reads X-Forwarded-Proto gets null.
Source
packages/runtime-node/src/runner.ts:278-297
PartialIncoming request URLrequest.url uses the scheme and host the client requested, usually https.request.url is always http://<Host header><path>. 1 file
Notes
Code that checks for https:// or builds absolute links from request.url sees http.
Source
packages/runtime-node/src/runner.ts:299-302
UnsupportedImmutable headers on incoming requestsrequest.headers on an incoming request is immutable. set() throws Can't modify immutable headers.Incoming request headers are mutable. Headers on fetch() responses are immutable, and set() throws TypeError: immutable. 2 files
Notes
Code that mutates incoming headers works on Orange and fails on Cloudflare.
Not verified by a test
Checked against undici 8.10.2 directly, not through a running Worker.
Source
packages/runtime-node/src/runner.ts:960-966packages/runtime-node/src/globals/http.ts:635-639
PartialOutbound request cf objectinit.cf on a subrequest controls Cloudflare cache, image, and security features.Request deep-clones cf and keeps it on request.cf, then sends nothing from it. 2/2 pass · 2 files
Notes
cacheControl conflicts with cacheTtl or the cache option throw as in workerd. cf-cache-control-test: 4 of 4 pass. Each cf option is listed in its own entry.
Tests
  • api-tests--cf-cache-control-test › cacheControlMutualExclusion Pass
  • api-tests--cf-cache-control-test › cacheControlSynthesis Pass
Source
packages/runtime-node/src/globals/http.ts:557-572packages/runtime-node/src/globals/http.ts:604-617
Unsupportedcf.cacheTtlSets the edge cache TTL for the subrequest response.Ignored. The request goes to the origin unchanged and no edge feature runs. 2 files
Notes
Orange has no edge cache, so subrequest responses are never cached. They do not go through the Cache API either, as in wrangler dev.
Source
packages/runtime-node/src/globals/http.ts:604-617packages/runtime-node/src/globals/http.ts:825-848
Unsupportedcf.cacheTtlByStatusSets edge cache TTLs per response status range.Ignored. The request goes to the origin unchanged and no edge feature runs. 2 files
Notes
Orange has no edge cache, so responses are never cached.
Source
packages/runtime-node/src/globals/http.ts:604-617packages/runtime-node/src/globals/http.ts:825-848
Unsupportedcf.cacheEverythingCaches every response, not only static file types.Ignored. The request goes to the origin unchanged and no edge feature runs. 2 files
Notes
Orange has no edge cache, so subrequest responses are never cached. They do not go through the Cache API either, as in wrangler dev.
Source
packages/runtime-node/src/globals/http.ts:604-617packages/runtime-node/src/globals/http.ts:825-848
Unsupportedcf.cacheKeySets a custom edge cache key.Ignored. The request goes to the origin unchanged and no edge feature runs. 2 files
Notes
Orange has no edge cache, so responses are never cached.
Source
packages/runtime-node/src/globals/http.ts:604-617packages/runtime-node/src/globals/http.ts:825-848
Unsupportedcf.cacheTagsTags the cached response for purge by tag.Ignored. The request goes to the origin unchanged and no edge feature runs. 2 files
Notes
Orange has no edge cache, so responses are never cached.
Source
packages/runtime-node/src/globals/http.ts:604-617packages/runtime-node/src/globals/http.ts:825-848
Unsupportedcf.cacheControlSends explicit Cache-Control directives to the edge cache.Validated against cacheTtl and the cache option, then ignored. 2 files
Notes
Orange has no edge cache, so responses are never cached.
Source
packages/runtime-node/src/globals/http.ts:557-572packages/runtime-node/src/globals/http.ts:825-848
Unsupportedcf.imageResizes and converts images with Image Resizing.Ignored. The request goes to the origin unchanged and no edge feature runs. 2 files
Unsupportedcf.polishOptimizes images with Polish.Ignored. The request goes to the origin unchanged and no edge feature runs. 2 files
Unsupportedcf.minifyMinifies JavaScript, CSS, and HTML in the response.Ignored. The request goes to the origin unchanged and no edge feature runs. 2 files
Unsupportedcf.mirageTurns on Mirage image loading.Ignored. The request goes to the origin unchanged and no edge feature runs. 2 files
Unsupportedcf.scrapeShieldTurns ScrapeShield features on or off.Ignored. The request goes to the origin unchanged and no edge feature runs. 2 files
Unsupportedcf.appsTurns Cloudflare Apps injection on or off.Ignored. The request goes to the origin unchanged and no edge feature runs. 2 files
Unsupportedcf.resolveOverrideSends the request to a different hostname in the same zone.Ignored. The request goes to the origin unchanged and no edge feature runs. 2 files
PartialRequest cache optioncache accepts no-store and no-cache. Other modes throw Unsupported cache mode. Before the cache_option_enabled flag, Request has no cache property.cache is always present. no-store and no-cache go to undici. Other modes, such as default, are accepted without an error and read back as undefined. 1/2 pass · 2 files
Notes
http-test cacheMode fails because 'cache' in Request.prototype is true without the flag.
Not verified by a test
Checked against undici 8.10.2 directly for the accepted default mode. What undici sends for no-store and no-cache is not checked.
Tests
  • api-tests--http-test › cacheMode AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: | | true !== false Fail · Behavior differs
  • api-tests--cf-cache-control-test › cacheControlWithCacheOption Pass
Source
packages/runtime-node/src/globals/http.ts:532-542packages/runtime-node/src/globals/http.ts:657-660
PartialIncoming request.signalWith enable_request_signal, request.signal aborts when the client disconnects.request.signal always aborts when the client aborts or closes the connection before the response ends. 3/3 pass · 1 file
Notes
No compat flag is needed. request-signal-enabled: 5 of 6 pass. abortedRequestDoesNotAbortSubrequest fails. request_signal_passthrough is not honored: requestPassedOverRpcIncludesSignal fails.
Tests
  • api-tests--request-signal-enabled › abortIfClientAbandonsRequest Pass
  • api-tests--request-signal-enabled › abortedRequestDoesNotAbortSubrequest Pass
  • api-tests--request-signal-passthrough › requestPassedOverRpcIncludesSignal Pass
Source
packages/runtime-node/src/runner.ts:954-966
Supportedfetch() with an AbortSignalinit.signal cancels an in-flight subrequest.Passes signal to undici, which cancels the request. 2/2 pass · 1 file
Notes
abortable-fetch-test: 6 of 7 pass. requestAbortSignal fails because new Request('') throws. See fetch-request-relative-url.
Tests
  • api-tests--abortable-fetch-test › timedAbort Pass
  • api-tests--abortable-fetch-test › syncSubrequest Pass
Source
packages/runtime-node/src/globals/http.ts:532-542
UnsupportedRequest with an empty or relative URLnew Request('') succeeds and gives a Request with an empty URL.new Request('') throws TypeError: Failed to parse URL from. 0/1 pass · 1 file
Notes
undici requires an absolute URL.
Tests
  • api-tests--abortable-fetch-test › requestAbortSignal TypeError: Failed to parse URL from Fail · Behavior differs
Source
packages/runtime-node/src/globals/http.ts:578-585
UnsupportedOutbound WebSocket through fetch()fetch() with Upgrade: websocket returns a 101 response whose webSocket property is the client end.fetch() rejects with TypeError: fetch failed, caused by invalid upgrade header from undici. 1 file
Notes
The error does not say that Orange lacks the feature.
Workaround
Use new WebSocket(url).
Not verified by a test
The undici error was reproduced with undici 8.10.2 directly, not through a running Worker.
Source
packages/runtime-node/src/globals/http.ts:825-848
PartialOutbound new WebSocket(url)new WebSocket(url) opens a client WebSocket. Inside a Durable Object, the connection waits for the output gate.Extends Node's built-in WebSocket and connects at once. 2/2 pass · 1 file
Notes
Connection setup does not wait for the Durable Object output gate. websocket-constructor-test: 18 of 18 pass.
Tests
  • api-tests--websocket-constructor-test › binaryTypeDefaultsToBlob Pass
  • api-tests--websocket-constructor-test › closeReasonTooLong Pass
Source
packages/runtime-node/src/globals/websocket.ts:502-519
SupportedInbound WebSocket upgradeA fetch handler accepts a WebSocket by returning new Response(null, { status: 101, webSocket }).The runtime calls fetch for the upgrade request and couples the returned WebSocketPair end to the network socket. 1/1 pass · 1 file
Notes
A non-101 response is written back as a plain HTTP response. A selected subprotocol that the client did not offer fails the upgrade. The upgrade request has no request.signal tied to the client.
Tests
  • api-tests--websocket-allow-half-open-test › autoCloseReplyWhenNotHalfOpen Pass
Source
packages/runtime-node/src/runner.ts:1016-1134
Supportedfetch() of data: URLsfetch() decodes data: URLs locally.undici decodes data: URLs locally. 2/2 pass · 1 file
Notes
data-url-fetch-test: 2 of 2 pass.
Tests
  • api-tests--data-url-fetch-test › dataUrl Pass
  • api-tests--data-url-fetch-test › base64DataUrl Pass
Source
packages/runtime-node/src/globals/http.ts:825-848
Supportedconnect() to a ctx.mapVirtualHost() hostctx.mapVirtualHost(fetcher, port) returns a .workers.alt host. connect() to that host goes through the fetcher.Returns a random <hex>.workers.alt:<port> host per fetcher. connect() to it calls the fetcher's connect(). 2/2 pass · 2 files
Notes
Only connect() uses the mapping. fetch() to that host goes to undici and fails DNS.
Not verified by a test
fetch() to a mapped host is read from code and not run.
Tests
  • api-tests--js-rpc-test › mapVirtualHostConnect Pass
  • api-tests--js-rpc-test › mapVirtualHostIdempotent Pass
Source
packages/runtime-node/src/internal/virtual-hosts.ts:13-26packages/runtime-node/src/modules/cloudflare-sockets/socket.ts:600-622
Partialcloudflare:sockets connect()TCP sockets leave through Cloudflare's network. Port 25 and Cloudflare IP ranges are blocked.Sockets connect directly from the host with node:net. No port or address is blocked. 1 file
Notes
Inside a Durable Object, connect() to the network does not wait for the output gate. Egress IP and network policy are the host's.
Source
packages/runtime-node/src/modules/cloudflare-sockets/socket.ts:596-653 Cloudflare docs
Supportedconnect() with secureTransport: "on"Opens a TLS connection with the hostname as SNI.Opens a node:tls connection with servername set to the hostname. 2 files
Notes
Invalid values throw Unsupported value in secureTransport socket option.
Not verified by a test
No saved test opens a real TLS socket through cloudflare:sockets.
Source
packages/runtime-node/src/modules/cloudflare-sockets/socket.ts:60-69packages/runtime-node/src/modules/cloudflare-sockets/socket.ts:625-647
Supportedsocket.startTls()Upgrades a socket opened with secureTransport: "starttls" to TLS.Upgrades the connection with node:tls and returns a new Socket. Misuse throws workerd's error messages. 1/1 pass · 1 file
Notes
transferredSocketCannotStartTls passes.
Not verified by a test
No saved test runs a full STARTTLS handshake.
Tests
  • api-tests--outbound-interceptor-socket-test › transferredSocketCannotStartTls Pass
Source
packages/runtime-node/src/modules/cloudflare-sockets/socket.ts:473-531
Supportedconnect() with allowHalfOpenallowHalfOpen: false closes the write side when the peer sends EOF. true keeps it open.Applies the same rule on top of a half-open node:net socket. 2/2 pass · 1 file
Notes
Both transferred-socket half-open tests pass.
Tests
  • api-tests--outbound-interceptor-socket-test › transferredSocketHonorsAllowHalfOpenFalse Pass
  • api-tests--outbound-interceptor-socket-test › transferredSocketHonorsAllowHalfOpenTrue Pass
Source
packages/runtime-node/src/modules/cloudflare-sockets/socket.ts:318-326
PartialStreaming request bodiesA ReadableStream body streams to the origin. A FixedLengthStream or expectedLength body is sent with Content-Length.Streams the body through undici with duplex: "half". Global fetch() ignores expectedLength and sends chunked encoding. 1/1 pass · 2 files
Notes
Service binding fetch() sets Content-Length from expectedLength. http-test test fails on a Transfer-Encoding check.
Not verified by a test
The chunked encoding on global fetch() is read from code and not run against an origin.
Tests
  • api-tests--http-test › http-test Pass
Source
packages/runtime-node/src/globals/http.ts:837-846packages/runtime-node/src/bindings/service.ts:236-241
SupportedResponse.json()Response.json(value, init) builds a JSON response.Builds the response with undici and accepts a Response as init. 2/2 pass · 1 file
Notes
response-json: 6 of 6 pass.
Tests
  • api-tests--response-json › basics Pass
  • api-tests--response-json › notJsonSerializable Pass
Source
packages/runtime-node/src/globals/http.ts:911-926
SupportedHeaders.getAll()Works only for Set-Cookie.Same. getAll() with another name throws TypeError. 2 files
Notes
Responses written to the client keep each Set-Cookie header separate.
Not verified by a test
No saved test covers getSetCookie() or getAll().
Source
packages/runtime-node/src/globals/http.ts:80-91packages/runtime-node/src/runner.ts:314-322
SupportedAutomatic response compression (Content-Encoding)When a Worker returns a Response with Content-Encoding: gzip or br, the runtime compresses the body.Compresses bodies whose Content-Encoding is exactly gzip or br, for Worker and Durable Object responses, and drops the stale Content-Length. Other codings are sent unchanged. 3 files
SupportedAutomatic decompression of fetch() responsesfetch() decodes gzip and br response bodies.undici decodes gzip, deflate, and br response bodies. 1 file
Notes
Unlike workerd, deflate bodies are also decoded.
Not verified by a test
Relies on undici defaults. Not run.
Source
packages/runtime-node/src/globals/http.ts:825-848
SupportedencodeBody: "manual" on ResponseencodeBody: "manual" sends an already compressed body as is.encodeBody: "manual" sends the bytes unchanged. A Response passed as init keeps the mode, and clone() resets it to automatic. 2 files
Notes
A service binding caller reads a manually encoded body decoded.
Source
packages/runtime-node/src/globals/http.ts:701-720src/commands/dev.test.ts:431-472
StubencodeResponseBody on RequestencodeResponseBody: "manual" keeps the response body compressed.new Request(url, { encodeResponseBody }) throws NotSupportedError: encodeResponseBody is not implemented yet. 1 file
Notes
Any value throws, including "automatic".
Source
packages/runtime-node/src/globals/http.ts:517-526

Node.js compat

Partialnode:assertworkerd's own assert module.Workerd-shaped override. Host Node.js assert, with rejects() and doesNotReject() changed to accept any thenable, such as RpcPromise. 1/4 pass · 2 files
Notes
assert-test: 49/52 pass. test_equal, test_deep_equal_errors, and test_check_proxies fail because Node.js formats and compares some values differently.
Tests
  • node-tests--assert-test › getterFailsIfGetterOptionsSetToFalse Pass
  • node-tests--assert-test › test_equal AssertionError [ERR_ASSERTION]: 1 != '1' Fail · Behavior differs
  • node-tests--assert-test › test_deep_equal_errors AssertionError [ERR_ASSERTION]: Expected values to be loosely deep-equal: | | [ Fail · Behavior differs
  • node-tests--assert-test › test_check_proxies AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal: | + actual - expected | Fail · Behavior differs
Source
src/build/rewrite-module-imports.ts:13packages/runtime-node/src/modules/node/assert.ts:3-6
Partialnode:assert/strictworkerd's strict assert.Workerd-shaped override. Re-exports the strict mode of the Orange node:assert. 2 files
Notes
Has the same differences as node:assert. No upstream test imports it on its own.
Not verified by a test
No conformance test covers node:assert/strict directly.
Source
src/build/rewrite-module-imports.ts:14packages/runtime-node/src/modules/node/assert-strict.ts:3-29
Supportednode:async_hooksAsyncLocalStorage and AsyncResource work. The low-level hooks APIs return fixed values. Bound and snapshot functions throw outside the request that made them.Stock Node.js node:async_hooks. 2/4 pass · 1 file
Notes
The low-level async hooks APIs return real values. Orange is looser than Cloudflare here: Node.js capabilities that workerd removes or stubs are available.
Tests
  • node-tests--async_hooks-nodejs-test › asyncLocalStorageOptions Pass
  • node-tests--bound-als-test › test AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: | | 200 !== 500 Fail · Behavior differs
  • api-tests--als-test › customthenable Pass
  • api-tests--als-only-test › customthenable Error: Expected an error to be thrown Fail · Behavior differs
Source
src/build/rewrite-module-imports.ts:12-21
Partialnode:bufferworkerd's own Buffer implementation, with kMaxLength 2147483647 and a 128 MiB isolate limit on transcode() output.Stock Node.js node:buffer, except that its Blob export is the global Blob, as on Cloudflare. 2/5 pass · 2 files
Notes
Bounds checks, error shapes, and limits are Node.js's. kMaxLength is 9007199254740991, and transcode() has no 128 MiB cap.
Tests
  • node-tests--buffer-nodejs-test › ascii Pass
  • node-tests--buffer-nodejs-test › overMaxLength AssertionError [ERR_ASSERTION]: Missing expected exception (RangeError). Fail · Behavior differs
  • node-tests--buffer-nodejs-test › readInt AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal: | + actual - expected | Fail · Behavior differs
  • node-tests--buffer-nodejs-test › outOfBoundsWrites RangeError [ERR_OUT_OF_RANGE]: The value of "sourceStart" is out of range. It must be >= 0 && <= 1024. Received 2048 Fail · Behavior differs
  • node-tests--buffer-base64-large-test › base64LargeBufferThrowsRangeError Pass
Source
src/build/rewrite-module-imports.ts:12-21packages/runtime-node/src/modules/node/buffer.ts
Supportednode:child_processEvery function and the ChildProcess constructor throw ERR_METHOD_NOT_IMPLEMENTED.Stock Node.js node:child_process. 0/1 pass · 1 file
Notes
Spawns real host processes. Orange is looser than Cloudflare here: Node.js capabilities that workerd removes or stubs are available.
Tests
  • node-tests--child_process-nodejs-test › testChildProcessConstructor AssertionError [ERR_ASSERTION]: Missing expected exception. Fail · Behavior differs
Source
src/build/rewrite-module-imports.ts:12-21
Supportednode:clusterA single-primary stub. fork(), disconnect(), and setupPrimary() throw ERR_METHOD_NOT_IMPLEMENTED.Stock Node.js node:cluster. 1/1 pass · 1 file
Notes
Forks real host processes. Orange is looser than Cloudflare here: Node.js capabilities that workerd removes or stubs are available.
Tests
  • node-tests--cluster-nodejs-test › clusterConstants Pass
Source
src/build/rewrite-module-imports.ts:12-21
Supportednode:consoleThe global console. Console, context(), and createTask() throw ERR_METHOD_NOT_IMPLEMENTED.Stock Node.js node:console. 0/1 pass · 1 file
Notes
The Console constructor works. Orange is looser than Cloudflare here: Node.js capabilities that workerd removes or stubs are available.
Tests
  • node-tests--console-nodejs-test › testNotImplemented AssertionError [ERR_ASSERTION]: Missing expected exception. Fail · Behavior differs
Source
src/build/rewrite-module-imports.ts:12-21
Supportednode:constantsA fixed constants table that is the same on every host.Stock Node.js node:constants. 0/1 pass · 1 file
Notes
Values are the host's. Orange is looser than Cloudflare here: Node.js capabilities that workerd removes or stubs are available.
Tests
  • node-tests--constants-test › constantsTest AssertionError [ERR_ASSERTION]: The expression evaluated to a falsy value: | | ok(key in constants) Fail · Behavior differs
Source
src/build/rewrite-module-imports.ts:12-21
Supportednode:cryptoworkerd's BoringSSL-backed node:crypto.Stock Node.js node:crypto over OpenSSL. KeyObject, publicEncrypt, and privateDecrypt work with keys from JWK and CryptoKey, as jose uses them. 3/4 pass · 2 files
Notes
Algorithms that workerd's BoringSSL build rejects work. Orange adds workerd's extra exports (the KeyObject subclasses, CryptoKey, pseudoRandomBytes, and throwing Cipher and createCipher stubs) in packages/runtime-node/src/modules/node/crypto.ts. Orange is looser than Cloudflare here: Node.js capabilities that workerd removes or stubs are available.
Tests
  • node-tests--crypto_keys-test › create_public_key AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal: | + actual - expected | Fail · Behavior differs
  • node-tests--crypto_cipher-test › cipheriv Pass
  • node-tests--crypto_hash-test › hash_correctness_tests Pass
  • api-tests--crypto-extras-test › aesCounterOverflowTest Pass
Source
src/build/rewrite-module-imports.ts:12-21src/runtime/node-crypto.test.ts
Supportednode:dgramAn inert dgram module. Workers cannot open UDP sockets.Stock Node.js node:dgram. 0/1 pass · 1 file
Notes
Opens real UDP sockets. Orange is looser than Cloudflare here: Node.js capabilities that workerd removes or stubs are available.
Tests
  • node-tests--dgram-nodejs-test › dgramTest AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal: | + actual - expected | Fail · Behavior differs
Source
src/build/rewrite-module-imports.ts:12-21
Supportednode:dnsResolves names over DNS over HTTPS to Cloudflare DNS. getServers() returns the 1.1.1.1 addresses.Stock Node.js node:dns. 1/2 pass · 1 file
Notes
Resolves through the host resolver. Orange is looser than Cloudflare here: Node.js capabilities that workerd removes or stubs are available.
Tests
  • node-tests--dns-nodejs-test › getServers AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal: | + actual - expected | Fail · Behavior differs
  • node-tests--dns-nodejs-test › functionsExist Pass
Source
src/build/rewrite-module-imports.ts:12-21
Supportednode:dns/promisesThe promise API of node:dns, over DNS over HTTPS to Cloudflare DNS.Stock Node.js node:dns/promises. 0/1 pass · 1 file
Notes
Resolves through the host resolver. Orange is looser than Cloudflare here: Node.js capabilities that workerd removes or stubs are available.
Tests
  • node-tests--dns-nodejs-test › getServers AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal: | + actual - expected | Fail · Behavior differs
Source
src/build/rewrite-module-imports.ts:12-21
Supportednode:domainA non-operational domain stub.Stock Node.js node:domain. 0/1 pass · 1 file
Notes
Domains work as in Node.js. Orange is looser than Cloudflare here: Node.js capabilities that workerd removes or stubs are available.
Tests
  • node-tests--domain-nodejs-test › domainTest AssertionError [ERR_ASSERTION]: The expression evaluated to a falsy value: | | ok(domain.create instanceof domain.Domain) Fail · Behavior differs
Source
src/build/rewrite-module-imports.ts:12-21
Supportednode:inspectorProcess-level inspector stubs. In production, the Session constructor throws.Stock Node.js node:inspector. 1/3 pass · 1 file
Notes
new Session() works instead of throwing. Orange is looser than Cloudflare here: Node.js capabilities that workerd removes or stubs are available.
Tests
  • node-tests--inspector-nodejs-test › inspectorSession AssertionError [ERR_ASSERTION]: Missing expected exception. Fail · Behavior differs
  • node-tests--inspector-nodejs-test › inspectorConsole Pass
  • node-tests--inspector-real-nodejs-test › defaultExportsArePresent AssertionError [ERR_ASSERTION]: Missing expected exception. Fail · Behavior differs
Source
src/build/rewrite-module-imports.ts:12-21
Supportednode:inspector/promisesThe promise inspector stubs. url(), open(), close(), and waitForDebugger() throw ERR_METHOD_NOT_IMPLEMENTED.Stock Node.js node:inspector/promises. 1 file
Notes
Session works instead of throwing. Orange is looser than Cloudflare here: Node.js capabilities that workerd removes or stubs are available.
Source
src/build/rewrite-module-imports.ts:12-21
Supportednode:netSockets connect through Cloudflare's TCP sockets (cloudflare:sockets). Unix domain sockets fail.Stock Node.js node:net. 0/3 pass · 1 file
Notes
Sockets are real host sockets without Cloudflare's egress rules. Orange is looser than Cloudflare here: Node.js capabilities that workerd removes or stubs are available.
Tests
  • node-tests--net-nodejs-test › testBlockList AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal: | + actual - expected | Fail · Behavior differs
  • node-tests--net-nodejs-test › testNetConnectAbortControllerPreAbort TypeError [ERR_MISSING_ARGS]: The "options" or "port" or "path" argument must be specified Fail · Behavior differs
  • node-tests--net-nodejs-test › testNetWriteCbOnDestroyBefureConnected RangeError [ERR_SOCKET_BAD_PORT]: Port should be >= 0 and < 65536. Received type number (NaN). Fail · Behavior differs
Source
src/build/rewrite-module-imports.ts:12-21
Supportednode:osFixed values that hide the host operating system.Stock Node.js node:os. 0/1 pass · 1 file
Notes
Reports the real host operating system. Orange is looser than Cloudflare here: Node.js capabilities that workerd removes or stubs are available.
Tests
  • node-tests--os-test › osTest AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: | | 16 !== 1 Fail · Behavior differs
Source
src/build/rewrite-module-imports.ts:12-21
Supportednode:pathPOSIX path functions. Relative paths resolve against / because Workers have no working directory.Stock Node.js node:path. 1/1 pass · 1 file
Notes
Error text matches Node.js. Orange is looser than Cloudflare here: Node.js capabilities that workerd removes or stubs are available.
Tests
  • node-tests--path-test › test_path Pass
Source
src/build/rewrite-module-imports.ts:12-21
Supportednode:path/posixThe POSIX path functions.Stock Node.js node:path/posix. 1/1 pass · 1 file
Notes
Error text matches Node.js. Orange is looser than Cloudflare here: Node.js capabilities that workerd removes or stubs are available.
Tests
  • node-tests--path-test › make_sure_posix_win32_works Pass
Source
src/build/rewrite-module-imports.ts:12-21
Supportednode:path/win32The Windows path functions.Stock Node.js node:path/win32. 1/1 pass · 1 file
Notes
Error text matches Node.js. Orange is looser than Cloudflare here: Node.js capabilities that workerd removes or stubs are available.
Tests
  • node-tests--path-test › make_sure_posix_win32_works Pass
Source
src/build/rewrite-module-imports.ts:12-21
Supportednode:perf_hooksThe global Performance API plus inert Node.js helpers. createHistogram() and monitorEventLoopDelay() throw ERR_METHOD_NOT_IMPLEMENTED.Stock Node.js node:perf_hooks. 0/2 pass · 1 file
Notes
Event loop utilization reflects the long-running Orange process. Orange is looser than Cloudflare here: Node.js capabilities that workerd removes or stubs are available.
Tests
  • node-tests--perf-hooks-nodejs-test › testEventCounts AssertionError [ERR_ASSERTION]: eventCounts should exist Fail · Behavior differs
  • node-tests--perf-hooks-nodejs-test › testPerformanceToJSON AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: | + actual - expected | Fail · Behavior differs
Source
src/build/rewrite-module-imports.ts:12-21
Supportednode:readlineAn inert readline module. Workers have no terminal.Stock Node.js node:readline. 0/1 pass · 1 file
Notes
Works as in Node.js. Orange is looser than Cloudflare here: Node.js capabilities that workerd removes or stubs are available.
Tests
  • node-tests--readline-nodejs-test › readlineCreateInterface TypeError: Cannot read properties of undefined (reading 'history') Fail · Behavior differs
Source
src/build/rewrite-module-imports.ts:12-21
Supportednode:readline/promisesAn inert readline/promises module.Stock Node.js node:readline/promises. 0/1 pass · 1 file
Notes
Works as in Node.js. Orange is looser than Cloudflare here: Node.js capabilities that workerd removes or stubs are available.
Tests
  • node-tests--readline-nodejs-test › readlineCreateInterface TypeError: Cannot read properties of undefined (reading 'history') Fail · Behavior differs
Source
src/build/rewrite-module-imports.ts:12-21
Supportednode:replA repl stub. start() and REPLServer throw ERR_METHOD_NOT_IMPLEMENTED.Stock Node.js node:repl. 1/1 pass · 1 file
Notes
Works as in Node.js. Orange is looser than Cloudflare here: Node.js capabilities that workerd removes or stubs are available.
Tests
  • node-tests--repl-nodejs-test › replBuiltinModules Pass
Source
src/build/rewrite-module-imports.ts:12-21
Supportednode:string_decoderworkerd's validating StringDecoder, with its state in a 7-byte buffer.Stock Node.js node:string_decoder. 1/1 pass · 1 file
Notes
Uses Node.js's native decoder. Orange is looser than Cloudflare here: Node.js capabilities that workerd removes or stubs are available.
Tests
  • node-tests--string-decoder-test › stringDecoderFuzz Pass
Source
src/build/rewrite-module-imports.ts:12-21
Partialnode:sysA deprecated alias of node:util.Workerd-shaped override that re-exports the Orange node:util. 1/1 pass · 2 files
Notes
sys-nodejs-test: 3/3 pass. Has the same differences as node:util.
Tests
  • node-tests--sys-nodejs-test › canBeImported Pass
Source
src/build/rewrite-module-imports.ts:16packages/runtime-node/src/modules/node/sys.ts:1-3
Partialnode:timersNode.js timers. workerd keeps the deprecated active(), unenroll(), and enroll() helpers.Workerd-shaped override. setTimeout() and setInterval() are Orange's global timers, so a Durable Object counts them, and they return Orange's Timeout objects. Immediates are the host's. Includes workerd's deprecated helpers. 2/3 pass · 2 files
Notes
timers-nodejs-test: 8/9 pass. testImmediateFromOtherContext fails because Orange does not throw when code uses an immediate from another request. timers-global-override-test: 13/13 pass.
Tests
  • node-tests--timers-nodejs-test › testEnroll Pass
  • node-tests--timers-nodejs-test › testImmediateFromOtherContext AssertionError: Missing expected exception. Fail · Behavior differs
  • node-tests--timers-global-override-test › testClearTimeoutAcceptsBothTypes Pass
Source
src/build/rewrite-module-imports.ts:19-20packages/runtime-node/src/modules/node/timers.ts:1-58
Partialnode:tlsTLS sockets connect through Cloudflare's TCP sockets. A custom checkServerIdentity throws because Workers cannot read the peer certificate. createSecurePair() throws.Stock Node.js node:tls. Connections are real host TLS sockets. 0/2 pass · 1 file
Notes
createSecurePair(), which Node.js 24 removed, is missing. Node.js validates ALPN input more strictly than workerd. Orange is looser than Cloudflare here: Node.js capabilities that workerd removes or stubs are available.
Tests
  • node-tests--tls-nodejs-test › testConvertALPNProtocols TypeError [ERR_INVALID_ARG_VALUE]: The argument 'ALPNProtocols' contains truncated protocol. Received <Buffer 61 62 63 64> Fail · Behavior differs
  • node-tests--tls-check-server-identity-test › regressionCheckServerIdentityConnect AssertionError [ERR_ASSERTION]: Missing expected exception: tls.connect() with custom checkServerIdentity must throw ERR_OPTION_NOT_IMPLEMENTED Fail · Behavior differs
Source
src/build/rewrite-module-imports.ts:12-21
Supportednode:ttyInert tty streams. isatty() returns false.Stock Node.js node:tty. 0/1 pass · 1 file
Notes
Reports the host terminal. Orange is looser than Cloudflare here: Node.js capabilities that workerd removes or stubs are available.
Tests
  • node-tests--tty-nodejs-test › ttyTest SystemError [ERR_TTY_INIT_FAILED]: TTY initialization failed: uv_tty_init returned EINVAL (invalid argument) Fail · Behavior differs
Source
src/build/rewrite-module-imports.ts:12-21
Partialnode:utilNode.js util with workerd changes: debuglog() always on, callbackify() on microtasks, and the is* helpers that Node.js 23 removed.Stock Node.js node:util plus log() and the is* helpers that Node.js 23 removed and Cloudflare still has. 0/4 pass · 2 files
Notes
inspect() output and call sites are Node.js's.
Tests
  • node-tests--util-nodejs-test › debuglog AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: | | 0 !== 1 Fail · Behavior differs
  • node-tests--util-nodejs-test › utilInspect AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: | + actual - expected | Fail · Behavior differs
  • node-tests--util-nodejs-test › getCallSitesTest AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: | | 10 !== 1 Fail · Behavior differs
  • node-tests--mimetype-test › test_ok AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: | + actual - expected | Fail · Behavior differs
Source
src/build/rewrite-module-imports.ts:12-21packages/runtime-node/src/modules/node/util.ts
Supportednode:v8A v8 stub. Heap snapshots, setFlagsFromString(), Serializer, and Deserializer throw ERR_METHOD_NOT_IMPLEMENTED.Stock Node.js node:v8. 0/1 pass · 1 file
Notes
Exposes the real V8 APIs. Orange is looser than Cloudflare here: Node.js capabilities that workerd removes or stubs are available.
Tests
  • node-tests--v8-nodejs-test › v8Test AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: | | 2521476671 !== 0 Fail · Behavior differs
Source
src/build/rewrite-module-imports.ts:12-21
Supportednode:vmA validating vm stub. Workers cannot compile code at runtime, so the run functions throw.Stock Node.js node:vm. 0/1 pass · 1 file
Notes
Compiles and runs code at runtime. Orange is looser than Cloudflare here: Node.js capabilities that workerd removes or stubs are available.
Tests
  • node-tests--vm-test › vmTest AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal: | + actual - expected | Fail · Behavior differs
Source
src/build/rewrite-module-imports.ts:12-21
Supportednode:wasiA validating WASI stub. The WASI methods throw ERR_METHOD_NOT_IMPLEMENTED.Stock Node.js node:wasi. 0/1 pass · 1 file
Notes
Node.js WASI works. Orange is looser than Cloudflare here: Node.js capabilities that workerd removes or stubs are available.
Tests
  • node-tests--wasi-nodejs-test › wasiTest AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal: | + actual - expected | Fail · Behavior differs
Source
src/build/rewrite-module-imports.ts:12-21
Supportednode:worker_threadsA single-thread stub. Worker and BroadcastChannel throw ERR_METHOD_NOT_IMPLEMENTED.Stock Node.js node:worker_threads. 0/1 pass · 1 file
Notes
Starts real worker threads. Its MessageChannel is Node.js's, not the global one. Orange is looser than Cloudflare here: Node.js capabilities that workerd removes or stubs are available.
Tests
  • node-tests--worker_threads-nodejs-test › testBroadcastChannelConstructor AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal: | + actual - expected | Fail · Behavior differs
Source
src/build/rewrite-module-imports.ts:12-21
Partialnode:zlibworkerd's zlib, with one-shot output capped at 128 MiB and a RangeError on overflow.Stock Node.js node:zlib, except crc32(), which accepts an ArrayBuffer as on Cloudflare. 2/6 pass · 2 files
Notes
One-shot output has no 128 MiB cap, and limits and errors are Node.js's.
Tests
  • node-tests--zlib-nodejs-test › brotli Pass
  • node-tests--zlib-nodejs-test › stateSizeTest orange process exited while running this test: Fail · One test crashes the whole runtime
  • node-tests--zlib-nodejs-test › zlibZeroByte AssertionError [ERR_ASSERTION]: End should have been called Fail · Behavior differs
  • node-tests--zlib-resizable-buffer-test › regression_AUTOVULN_CLOUDFLARE_WORKERD_295_writeSync_input orange process exited while running this test: Fail · One test crashes the whole runtime
  • node-tests--zlib-invalid-mode-test › zlibInvalidModeIsRejected orange process exited while running this test: Fail · One test crashes the whole runtime
  • node-tests--zlib-zstd-nodejs-test › zstdBasicSyncTest Pass
Source
src/build/rewrite-module-imports.ts:12-21packages/runtime-node/src/modules/node/zlib.ts
Supportednode:_http_commonA subset of Node.js _http_common, with the method list sorted.Stock Node.js node:_http_common. 1/1 pass · 1 file
Notes
Exports Node.js's list. Orange is looser than Cloudflare here: Node.js capabilities that workerd removes or stubs are available.
Tests
  • node-tests--http-nodejs-test › testHttpCommon Pass
Source
src/build/rewrite-module-imports.ts:12-21
Supportednode:_stream_duplexThe legacy module name for stream.Duplex, with named exports.Stock Node.js node:_stream_duplex. 1 file
Notes
Same as Node.js. Orange is looser than Cloudflare here: Node.js capabilities that workerd removes or stubs are available.
Source
src/build/rewrite-module-imports.ts:12-21
Supportednode:_stream_passthroughThe legacy module name for stream.PassThrough, with named exports.Stock Node.js node:_stream_passthrough. 1 file
Notes
Same as Node.js. Orange is looser than Cloudflare here: Node.js capabilities that workerd removes or stubs are available.
Source
src/build/rewrite-module-imports.ts:12-21
Supportednode:_stream_readableThe legacy module name for stream.Readable, with named exports.Stock Node.js node:_stream_readable. 1 file
Notes
Same as Node.js. Orange is looser than Cloudflare here: Node.js capabilities that workerd removes or stubs are available.
Source
src/build/rewrite-module-imports.ts:12-21
Supportednode:_stream_transformThe legacy module name for stream.Transform, with named exports.Stock Node.js node:_stream_transform. 1 file
Notes
Same as Node.js. Orange is looser than Cloudflare here: Node.js capabilities that workerd removes or stubs are available.
Source
src/build/rewrite-module-imports.ts:12-21
Supportednode:_stream_writableThe legacy module name for stream.Writable, with named exports.Stock Node.js node:_stream_writable. 1 file
Notes
Same as Node.js. Orange is looser than Cloudflare here: Node.js capabilities that workerd removes or stubs are available.
Source
src/build/rewrite-module-imports.ts:12-21
Partialnode:fsA virtual file system. /bundle holds the Worker's modules, /tmp is per request, and /dev has null, zero, full, and random.Stock Node.js node:fs on the host disk. Paths under /bundle map to the Worker's bundled files and are read-only: writes fail with EPERM. /tmp maps to a private directory for each request and each Durable Object, removed when it ends, as in workerd. Outside every event /tmp is one writable directory for the process, and files have no size limit, as in Node.js. 2/3 pass · 5 files
Notes
workerd makes /tmp read-only during module evaluation and stops a file at 128 MiB; Orange follows Node.js for both. The /tmp files are on disk, not in memory. Every other path is the host path. workerd's 15 fs test files run unmodified. 153 tests pass. 105 fail on stock Node.js too, so they test workerd-only behavior, such as a / that holds only /bundle, /tmp, and /dev, files owned by uid 0, path limits, and workerd error codes. opendirSyncAndAsyncTest2 is not run because it lists the whole host disk.
Tests
  • node-tests--fs-cp-test › copyDirectoryToExistingDirectory Pass
  • node-tests--fs-readstream-test › readStreamTest1 Pass
  • node-tests--fs-dir-test › mkdirSyncTest AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal: | + actual - expected | Fail · fs is the host disk, not a virtual fs
Source
packages/runtime-node/src/modules/node-fs/bundle-paths.tspackages/runtime-node/src/internal/worker-tmp.tssrc/runtime/node-fs.test.tstests/worker-tmp.test.tspackages/cloudflare-conformance/upstream.json
Partialnode:fs/promisesThe promise API of the virtual file system.Stock Node.js node:fs/promises with the /bundle and /tmp mapping of node:fs. 0/1 pass · 2 files
Notes
Has the same /bundle and /tmp differences as node:fs. fs-stat-test fails on stock Node.js too, because it expects workerd's virtual root and uid 0.
Tests
  • node-tests--fs-stat-test › statPromisesTest AssertionError [ERR_ASSERTION]: Missing expected rejection. Fail · fs is the host disk, not a virtual fs
Source
src/build/rewrite-module-imports.ts:63-66packages/runtime-node/src/modules/node-fs/promises.ts
Partialnode:httpClients send requests through fetch(). Servers do not bind a port. cloudflare:node routes requests to them by port.Workerd-shaped override. Servers register in a per-Worker port map like workerd. ClientRequest is host Node.js and opens a real host connection, with workerd's path-only target check. 2/5 pass · 3 files
Notes
http-server-nodejs-test: 21/29 pass. http-outgoing-nodejs-test: 11/15 pass, and 2 tests hang. http-client-nodejs-test: 6/7 pass, testHttpRequestHostHeader hangs. http-nodejs-test: 7/8 pass. http-client-path-ssrf-test: 7/7 pass. Client requests do not go through the Worker's fetch() path.
Tests
  • node-tests--http-client-path-ssrf-test › testRejectsAbsoluteUrlPath Pass
  • node-tests--http-server-nodejs-test › testIncomingMessageSocket Pass
  • node-tests--http-server-nodejs-test › testHttpServerNonUtf8Header AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: | | 'bÃ¥r' !== 'bår' Fail · Behavior differs
  • node-tests--http-outgoing-nodejs-test › testHttpOutgoingEndMultiple TimeoutError: The operation was aborted due to timeout Fail · Hangs (60s timeout)
  • node-tests--http-client-nodejs-test › testHttpRequestHostHeader TimeoutError: The operation was aborted due to timeout Fail · Hangs (60s timeout)
Source
src/build/rewrite-module-imports.ts:66packages/runtime-node/src/modules/node-http/index.ts:1-4packages/runtime-node/src/modules/node-http/index.ts:175-208
Partialnode:diagnostics_channelworkerd's diagnostics_channel. Tail Workers receive published messages.Passthrough. The import resolves to the host Node.js 24 module. 1/2 pass · 1 file
Notes
diagnostics-channel-test: 5/7 pass. test_channel_hasSubscribers_is_a_method and test_tracingChannel_hasSubscribers_is_a_method fail because hasSubscribers is a getter in Node.js 24. diagnostics-channel-getter-test: 2/2 pass.
Tests
  • node-tests--diagnostics-channel-test › test_channel_hasSubscribers_is_a_method AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: | + actual - expected | Fail · Behavior differs
  • node-tests--diagnostics-channel-getter-test › test_channel_hasSubscribers_is_a_getter Pass
Source
src/build/bundle-worker.ts:345-352
Supportednode:eventsworkerd's EventEmitter implementation.Passthrough. The import resolves to the host Node.js 24 module. 1/1 pass · 1 file
Notes
node-compat-v2-test nodeJsEventsExports passes.
Not verified by a test
Only the export shape is tested. EventEmitter behavior is not compared with workerd.
Tests
  • node-tests--node-compat-v2-test › nodeJsEventsExports Pass
Source
src/build/bundle-worker.ts:345-352
Unsupportednode:http2A stub. createServer(), createSecureServer(), and connect() throw ERR_METHOD_NOT_IMPLEMENTED. Only constants work.Passthrough. The import resolves to the host Node.js 24 module. 1/1 pass · 1 file
Notes
http2-test: 1/1 pass, but it checks only exports. In Orange, http2.connect() opens a real host HTTP/2 connection where Cloudflare throws.
Not verified by a test
The live http2.connect() behavior in Orange is from code reading, not a test.
Tests
  • node-tests--http2-test › http2Test Pass
Source
src/build/bundle-worker.ts:345-352
Partialnode:httpsClients send requests through fetch(). Servers are behind the http server modules flag.Passthrough. The import resolves to the host Node.js 24 module. 1/1 pass · 1 file
Notes
http-agent-nodejs-test testHttpsAgentConstructor passes. Requests use host TLS and do not get the node:http path-only target check.
Not verified by a test
https request behavior is not covered by a passing or failing conformance test.
Tests
  • node-tests--http-agent-nodejs-test › testHttpsAgentConstructor Pass
Source
src/build/bundle-worker.ts:345-352
Partialnode:modulecreateRequire() resolves modules in the Worker bundle. Most other members throw ERR_METHOD_NOT_IMPLEMENTED.Passthrough. The import resolves to the host Node.js 24 module. 2/3 pass · 1 file
Notes
module-create-require-test doTheTest fails with Cannot find module 'foo' because the host resolver does not see bundle modules. module-nodejs-test testUnimplemented passes. module-require-mutable-exports-test: 7/7 pass.
Tests
  • node-tests--module-create-require-test › doTheTest Error: Cannot find module 'foo' | Require stack: | - /noop.js Fail · Behavior differs
  • node-tests--module-create-require-test › isBuiltinTest Pass
  • node-tests--module-nodejs-test › testUnimplemented Pass
Source
src/build/bundle-worker.ts:345-352
Unsupportednode:processworkerd's process object, with process.env from text bindings and fixed values for host fields.Passthrough. The import resolves to the host Node.js 24 module. 0/2 pass · 1 file
Notes
process-nodejs-test: 0/24 and process-legacy-nodejs-test: 0/6 pass. See the process global entry.
Tests
  • node-tests--process-nodejs-test › processEnv local | env.DUB Variable local | env.FOO Variable local Fail · File fails at load
  • node-tests--process-legacy-nodejs-test › processLegacyNamedExports AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal: | + actual - expected | Fail · Behavior differs
Source
src/build/bundle-worker.ts:345-352
Supportednode:punycodeThe deprecated punycode module.Passthrough. The import resolves to the host Node.js 24 module. 1/1 pass · 1 file
Notes
punycode-nodejs-test: 1/1 pass. Node.js prints a deprecation warning on import.
Not verified by a test
The deprecation warning is from Node.js docs, not checked in Orange.
Tests
  • node-tests--punycode-nodejs-test › testPunycode Pass
Source
src/build/bundle-worker.ts:345-352
Supportednode:querystringThe querystring module.Passthrough. The import resolves to the host Node.js 24 module. 1/1 pass · 1 file
Notes
querystring-nodejs-test: 4/4 pass.
Tests
  • node-tests--querystring-nodejs-test › testQueryStringEscape Pass
Source
src/build/bundle-worker.ts:345-352
Unsupportednode:sqliteExports DatabaseSync, StatementSync, backup, and constants, but new DatabaseSync() throws because the constructor is not exposed. backup() throws.Passthrough. The import resolves to the host Node.js 24 module. 0/1 pass · 1 file
Notes
sqlite-nodejs-test testExports fails because the constants table differs. Host DatabaseSync works and opens SQLite files on the host disk.
Not verified by a test
That new DatabaseSync() works in Orange is from Node.js 24 behavior, not a test.
Tests
  • node-tests--sqlite-nodejs-test › testExports AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal: | + actual - expected | Fail · Not-implemented API
Source
src/build/bundle-worker.ts:345-352
Partialnode:streamworkerd's port of Node.js streams.Passthrough. The import resolves to the host Node.js 24 module. 2/4 pass · 1 file
Notes
streams-test: 135/141 pass. duplexDestroy fails, and readable_reading_readingmore, readable_short_stream, readable_object_multi_push_async, duplexReadableWritable, and transform_final hang. streams-nodejs-test: 5/5 pass. streams-v24-nodejs-test: 1/1 pass.
Tests
  • node-tests--streams-test › autoDestroy Pass
  • node-tests--streams-test › duplexDestroy undefined Fail · Behavior differs
  • node-tests--streams-test › transform_final TimeoutError: The operation was aborted due to timeout Fail · Hangs (60s timeout)
  • node-tests--streams-nodejs-test › testStreamReadableData Pass
Source
src/build/bundle-worker.ts:345-352
Supportednode:stream/consumersThe stream/consumers helpers.Passthrough. The import resolves to the host Node.js 24 module. 1 file
Notes
No upstream test imports it directly.
Not verified by a test
No conformance test covers node:stream/consumers.
Source
src/build/bundle-worker.ts:345-352
Supportednode:stream/promisesThe stream/promises helpers.Passthrough. The import resolves to the host Node.js 24 module. 1 file
Notes
No upstream test imports it directly.
Not verified by a test
No conformance test covers node:stream/promises.
Source
src/build/bundle-worker.ts:345-352
Partialnode:stream/webRe-exports the global web stream classes.Passthrough. The import resolves to the host Node.js 24 module. 1 file
Notes
Exports the host Node.js web stream classes. Orange replaces some web stream globals, so the classes here may not be the same objects as the globals.
Not verified by a test
Identity between node:stream/web exports and the Orange globals is not checked.
Source
src/build/bundle-worker.ts:345-352
Unsupportednode:testExports only mock, MockTracker, and MockFunctionContext.Passthrough. The import resolves to the host Node.js 24 module. 1 file
Notes
Exports the full host Node.js test runner, including test() and describe(). Code that uses more than mock works in Orange and fails on Cloudflare.
Not verified by a test
No conformance test covers node:test. The workerd export list is from src/node/test.ts at b73ce3a.
Source
src/build/bundle-worker.ts:345-352
Supportednode:timers/promisesPromise versions of the timers.Workerd-shaped override, ported from workerd on Orange's global timers, so a Durable Object counts them. 1/1 pass · 1 file
Notes
timers-nodejs-test imports it for its promisified timer tests.
Tests
  • node-tests--timers-nodejs-test › timersImmediatePromise Pass
Source
packages/runtime-node/src/modules/node/timers-promises.ts:1-210
Partialnode:trace_eventsAn inert trace_events stub.Passthrough. The import resolves to the host Node.js 24 module. 1/1 pass · 1 file
Notes
trace-events-nodejs-test: 1/1 pass. createTracing() returns a working host tracing object, not an inert one.
Not verified by a test
The host tracing difference is from code reading, not a test.
Tests
  • node-tests--trace-events-nodejs-test › traceEventsTest Pass
Source
src/build/bundle-worker.ts:345-352
Partialnode:urlworkerd's url module over its WHATWG URL implementation.Passthrough. The import resolves to the host Node.js 24 module. 2/2 pass · 1 file
Notes
url-nodejs-test: 8/8 pass. legacy_url-nodejs-test: 6/7 pass. formatWhatwg fails.
Tests
  • node-tests--url-nodejs-test › testDomainAsciiUnicode Pass
  • node-tests--legacy_url-nodejs-test › formatWhatwg Pass
Source
src/build/bundle-worker.ts:345-352
Supportednode:util/typesThe util/types predicates.Passthrough. The import resolves to the host Node.js 24 module. 1 file
Notes
No upstream test imports it directly.
Not verified by a test
No conformance test covers node:util/types.
Source
src/build/bundle-worker.ts:345-352
Partialnode:_http_agentworkerd's _http_agent module, part of its fetch-based node:http.Passthrough. The import resolves to the host Node.js 24 module. 1 file
Notes
Bypasses the Orange node:http override. For example, a Server from node:_http_server binds a real host port instead of the per-Worker port map.
Not verified by a test
Passthrough is from the rewrite list. No conformance test imports this module name directly.
Source
src/build/bundle-worker.ts:345-352
Partialnode:_http_clientworkerd's _http_client module, part of its fetch-based node:http.Passthrough. The import resolves to the host Node.js 24 module. 1 file
Notes
Bypasses the Orange node:http override. For example, a Server from node:_http_server binds a real host port instead of the per-Worker port map.
Not verified by a test
Passthrough is from the rewrite list. No conformance test imports this module name directly.
Source
src/build/bundle-worker.ts:345-352
Partialnode:_http_incomingworkerd's _http_incoming module, part of its fetch-based node:http.Passthrough. The import resolves to the host Node.js 24 module. 1 file
Notes
Bypasses the Orange node:http override. For example, a Server from node:_http_server binds a real host port instead of the per-Worker port map.
Not verified by a test
Passthrough is from the rewrite list. No conformance test imports this module name directly.
Source
src/build/bundle-worker.ts:345-352
Partialnode:_http_outgoingworkerd's _http_outgoing module, part of its fetch-based node:http.Passthrough. The import resolves to the host Node.js 24 module. 1 file
Notes
Bypasses the Orange node:http override. For example, a Server from node:_http_server binds a real host port instead of the per-Worker port map.
Not verified by a test
Passthrough is from the rewrite list. No conformance test imports this module name directly.
Source
src/build/bundle-worker.ts:345-352
Partialnode:_http_serverworkerd's _http_server module, part of its fetch-based node:http.Passthrough. The import resolves to the host Node.js 24 module. 1 file
Notes
Bypasses the Orange node:http override. For example, a Server from node:_http_server binds a real host port instead of the per-Worker port map.
Not verified by a test
Passthrough is from the rewrite list. No conformance test imports this module name directly.
Source
src/build/bundle-worker.ts:345-352
Partialnode:_stream_wrapA legacy stream wrapper module, behind enable_nodejs_stream_wrap_module.Passthrough. The import resolves to the host Node.js 24 module. 1 file
Notes
Exports the host Node.js JSStreamSocket wrapper.
Not verified by a test
No conformance test covers node:_stream_wrap.
Source
src/build/bundle-worker.ts:345-352
Partialnode:_tls_commonworkerd's _tls_common module, part of its node:tls.Passthrough. The import resolves to the host Node.js 24 module. 1 file
Notes
Bypasses the Orange node:tls override, so checkServerIdentity and the other workerd changes do not apply.
Not verified by a test
No conformance test imports this module name directly.
Source
src/build/bundle-worker.ts:345-352
Partialnode:_tls_wrapworkerd's _tls_wrap module, part of its node:tls.Passthrough. The import resolves to the host Node.js 24 module. 1 file
Notes
Bypasses the Orange node:tls override, so checkServerIdentity and the other workerd changes do not apply.
Not verified by a test
No conformance test imports this module name directly.
Source
src/build/bundle-worker.ts:345-352
Supportedcloudflare:nodehttpServerHandler() and handleAsNodeRequest() route fetch requests to node:http servers by port.Orange module that routes fetch requests to servers in the per-Worker port map. 1/1 pass · 2 files
Notes
http-server-nodejs-global-test imports httpServerHandler and passes. The node:http server gaps apply.
Tests
  • node-tests--http-server-nodejs-global-test › checkItWorks Pass
Source
src/build/rewrite-module-imports.ts:38-41packages/runtime-node/src/modules/cloudflare-node/index.ts:43-90
Unsupportednode: modules that workerd does not shipAn import of a node: module that workerd does not ship, such as node:sea, fails with No such module.esbuild runs with platform node, so every node: import that is not in the rewrite list resolves to the host Node.js module at runtime. 2 files
Notes
Code can use host-only modules in Orange and then fail on Cloudflare.
Not verified by a test
No test imports a host-only module.
Source
src/build/bundle-worker.ts:345-352src/build/bundle-worker.ts:82-96
Partialnode: imports without nodejs_compatnode: imports need nodejs_compat, which is on by default from compatibility date 2026-08-04. Without it, or with no_nodejs_compat, the imports fail.node: imports always work. Orange ignores compatibility_flags, including nodejs_compat and no_nodejs_compat. For nodejs_compat it warns that Node.js APIs are always on, and it warns about the other flags as ignored. 3 files
Notes
Orange runs one profile at 2026-09-03, where nodejs_compat is on by default. A Worker with an older date and no flag works in Orange but fails on Cloudflare.
Not verified by a test
The 2026-08-04 default date is from workerd compatibility-date.capnp at b73ce3a. Behavior with no_nodejs_compat is from code reading.
Source
src/config/profile.ts:1-2src/config/load-wrangler.ts:441-466src/build/bundle-worker.ts:82-96
SupportedBuilt-in imports without the node: prefixWith nodejs_compat_v2, imports such as 'fs' and 'assert' resolve to the same module as 'node:fs'.The bundler maps bare names to the same rewrite or passthrough as the node: name. 1/1 pass · 1 file
Notes
node-compat-v2-test checks that both names give the same module at load.
Tests
  • node-tests--node-compat-v2-test › nodeJsExpectedGlobals Pass
Source
src/build/bundle-worker.ts:80-96
Unsupportedprocess globalA workerd process object. Host fields such as platform, cwd(), and versions have fixed values. process.exit() ends the request with an error.The host Node.js process object of the runtime process. 1/4 pass · 1 file
Notes
process-nodejs-test: 0/24 pass because the module fails at load. process-legacy-nodejs-test: 0/6 pass. process-stdio-nodejs-test: 7/8 pass. Workers can read and change the runtime's real process state.
Not verified by a test
The process-nodejs-test load failure cause is not traced to one assertion.
Tests
  • node-tests--process-nodejs-test › processPlatform local | env.DUB Variable local | env.FOO Variable local Fail · File fails at load
  • node-tests--process-legacy-nodejs-test › processLegacyGlobalProcess AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal: | + actual - expected | Fail · Behavior differs
  • node-tests--process-stdio-nodejs-test › processStdioPropertiesTest AssertionError [ERR_ASSERTION]: stdout should have _type "fs" | | 'pipe' !== 'fs' Fail · Behavior differs
  • node-tests--process-stdio-nodejs-test › lineBufferTruncationTest Pass
Source
packages/runtime-node/src/runner.ts:912-928
Partialprocess.envWith nodejs_compat after 2025-04-01 (nodejs_compat_populate_process_env), process.env holds the Worker's text and JSON string bindings.Text vars and secrets are copied to process.env as strings, and JSON vars as JSON strings, as in workerd. They are layered over the host process.env. 1/2 pass · 4 files
Notes
Host variables, including RIVETKIT_STORAGE_PATH and host secrets, stay visible to Worker code. A var named like a RivetKit setting also changes the runtime's own configuration.
Workaround
Read values from env or import { env } from "cloudflare:workers".
Tests
  • node-tests--process-nodejs-test › processEnv local | env.DUB Variable local | env.FOO Variable local Fail · File fails at load
  • node-tests--process-legacy-nodejs-test › processLegacyFunctionality Pass
Source
packages/runtime-node/src/runner.ts:263-276packages/runtime-node/src/runner.ts:769packages/runtime-node/src/globals/cloudflare.ts:79src/commands/dev.test.ts:499-547
Unsupportedprocess.exit()Ends the current request with an error. The isolate keeps running.Host process.exit() ends the whole Orange runtime process. 0/2 pass
Notes
process-exit-test: 0/2 pass. The runtime exits before it is ready.
Tests
  • node-tests--process-exit-test › test 🍊 open-orange v0.0.1 · by rivet.dev | | Worker node-tests--process-exit-test Fail · File fails at load
  • node-tests--process-exit-test › test2 🍊 open-orange v0.0.1 · by rivet.dev | | Worker node-tests--process-exit-test Fail · File fails at load
PartialBuffer globalThe global Buffer is workerd's node:buffer Buffer.The host Node.js Buffer, patched so toString() throws a RangeError on oversized output and UTF-16 search at an odd offset does not hang. 2/2 pass · 2 files
Notes
node-compat-v2-test nodeJsExpectedGlobals passes, so the global and the node:buffer export are the same class. The node:buffer differences apply.
Tests
  • node-tests--node-compat-v2-test › nodeJsExpectedGlobals Pass
  • api-tests--buffer-indexof-odd-offset-ucs2-test › BufferIndexOfUnalignedUtf16 Pass
Source
packages/runtime-node/src/globals/buffer.ts:11-54packages/runtime-node/src/globals/install.ts:37
PartialBuffer size limitsbuffer.kMaxLength is 2147483647. Larger allocations throw a RangeError. transcode() output is capped at 128 MiB.buffer.kMaxLength is the Node.js 24 value, 9007199254740991. transcode() has no output cap. 1/3 pass · 1 file
Notes
Allocations above 2147483647 bytes succeed, where Cloudflare throws a RangeError.
Tests
  • node-tests--buffer-nodejs-test › overMaxLength AssertionError [ERR_ASSERTION]: Missing expected exception (RangeError). Fail · Behavior differs
  • node-tests--buffer-nodejs-test › toStringRangeError AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal: | + actual - expected | Fail · Behavior differs
  • node-tests--buffer-base64-large-test › base64LargeBufferThrowsRangeError Pass
Source
packages/runtime-node/src/modules/node/buffer.ts

Compatibility flags

Unsupportedcompatibility_dateSelects runtime behavior by date. Each flag with an enable date turns on for Workers with that date or later.Accepted with no warning, and nothing applies it. The runtime always behaves like workerd at 2026-09-03 with nodejs_compat. A missing date defaults to 2026-09-03. 3 files
Notes
The date only reaches the normalized configuration that feeds version metadata. A Worker with an older or newer date gets the 2026-09-03 behavior.
Source
src/config/profile.ts:1src/config/load-wrangler.ts:448packages/runtime-node/src/globals/cloudflare.ts:1-4
Unsupportedcompatibility_flagsTurns individual runtime behaviors on or off, on top of the compatibility date.Ignored. Config load prints [config-warning] Orange ignores compatibility_flags ["..."] with every distinct flag, sorted. The Node.js flags nodejs_compat, nodejs_compat_v2, and nodejs_als get Orange always has Node.js APIs, so it does not need compatibility_flags ["..."] instead. 3 files
Notes
The supported flag list is empty, so every flag gets a warning. The Worker still starts.
Source
src/config/profile.ts:2src/config/load-wrangler.ts:449-465src/commands/dev.ts:206-208
PartialCloudflare.compatibilityFlagsA frozen, prototype-less object that reports each enable flag as true or false for the running Worker.A frozen, prototype-less table with fixed values for the 2026-09-03 profile with nodejs_compat. Configured flags do not change it, and the runtime does not read it. 2/2 pass · 1 file
Notes
Some values do not match runtime behavior. See the flag entries. compat-flags-test and compat-flag-enabled-test pass.
Tests
  • api-tests--compat-flags-test › compatFlagsTest Pass
  • api-tests--compat-flag-enabled-test › compatFlagEnabledTest Pass
Source
packages/runtime-node/src/globals/cloudflare.ts:193-199
Supportednodejs_compatEnables Node.js built-in modules and globals. On by default for compatibility dates on or after 2026-08-04.Always on. Built-in modules resolve whether or not the flag is set, and the table reports true. 3 files
Notes
Setting the flag prints the ignored-flag warning. no_nodejs_compat is also ignored, so built-ins still resolve.
Source
src/build/rewrite-module-imports.ts:12-21packages/runtime-node/src/globals/cloudflare.ts:26src/config/load-wrangler.ts:450-457
Partialnodejs_compat_v2Implied by nodejs_compat on recent dates. Adds Node.js globals such as Buffer and process, and process.getBuiltinModule().Always on, and the table reports true. node-compat-v2-test passes 4 of 5. 1/2 pass · 1 file
Notes
nodeJsGetBuiltins fails. A node:fs or node:path module in the Worker bundle does not override the built-in the way workerd does, or process.getBuiltinModule() returns a different module.
Not verified by a test
Which half of nodeJsGetBuiltins fails is not checked.
Tests
  • node-tests--node-compat-v2-test › nodeJsGetBuiltins AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: | + actual - expected | Fail · Behavior differs
  • node-tests--node-compat-v2-test › nodeJsExpectedGlobals Pass
Source
packages/runtime-node/src/globals/cloudflare.ts:55
Supportedjs_rpcExperimental and off. A Durable Object class that does not extend DurableObject rejects RPC.Off, the same as Cloudflare. RPC to a plain class fails with The receiving Durable Object does not support RPC, because its class was not declared with \extends DurableObject\.... 1/2 pass · 2 files
Notes
Turning the flag on has no effect, so js-rpc-flag fails. Cloudflare does not deploy experimental flags.
Tests
  • api-tests--js-rpc-test › actorWithoutExtendsRejectsRpc Pass
  • api-tests--js-rpc-flag › main TypeError: The receiving Durable Object does not support RPC, because its class was not declared with `extends DurableObject`. In order to enable RPC, make sure your class extends the special class `D Fail · Behavior differs
Source
packages/runtime-node/src/globals/cloudflare.ts:44packages/runtime-node/src/bindings/durable-objects/rpc/methods.ts:80-87
Partialenable_request_signalOff by default. Without the flag, the incoming request.signal never aborts.The table says false, but the incoming request.signal always aborts when the client disconnects or stops reading the response. 3/3 pass · 2 files
Notes
Code that works in Orange because request.signal aborts does not get the abort on Cloudflare unless the flag is set. request-signal-enabled passes 5 of 6. abortedRequestDoesNotAbortSubrequest fails.
Workaround
Set enable_request_signal in the Wrangler config so Cloudflare matches Orange.
Tests
  • api-tests--request-signal-enabled › abortIfClientAbandonsRequest Pass
  • api-tests--request-signal-enabled › abortedRequestDoesNotAbortSubrequest Pass
  • api-tests--request-signal-disabled › incomingRequestSignalCanBeCloned Pass
Source
packages/runtime-node/src/globals/cloudflare.ts:93packages/runtime-node/src/runner.ts:954-966
Partialrequest_signal_passthroughOff by default. When on, a Request passed over RPC keeps its signal.Off. The table says false. A Request passed over RPC has no signal, and setting the flag does not change that. 2/2 pass · 1 file
Notes
The default side passes requestPassedOverRpcDoesNotIncludeSignal. The opt-in side fails request-signal-passthrough.
Tests
  • api-tests--request-signal-enabled › requestPassedOverRpcDoesNotIncludeSignal Pass
  • api-tests--request-signal-passthrough › requestPassedOverRpcIncludesSignal Pass
Source
packages/runtime-node/src/globals/cloudflare.ts:88
Supportedenable_nodejs_inspector_local_devExperimental and local-dev only. Without it, the node:inspector Session constructor throws.Stock Node.js node:inspector. 0/1 pass · 1 file
Notes
Session works as if the flag is on. Orange is looser than Cloudflare here: Node.js capabilities that workerd removes or stubs are available.
Tests
  • node-tests--inspector-nodejs-test › inspectorSession AssertionError [ERR_ASSERTION]: Missing expected exception. Fail · Behavior differs
Source
src/build/rewrite-module-imports.ts:12-21
Partialnodejs_compat_populate_process_envImplied by nodejs_compat after 2025-04-01. Text and JSON bindings appear on process.env, and nothing else does.On. Vars and secrets are copied to process.env, over the host environment of the runtime process. 0/1 pass · 3 files
Notes
Host variables such as RIVETKIT_STORAGE_PATH are visible. See process-env.
Tests
  • node-tests--process-nodejs-test › processEnv local | env.DUB Variable local | env.FOO Variable local Fail · File fails at load
Source
packages/runtime-node/src/globals/cloudflare.ts:79packages/runtime-node/src/runner.ts:263-276src/commands/dev.test.ts:499-547
Supporteddurable_object_alarmsObsolete. Alarms are on for every Worker, and the flag reads false.The table says false, and alarms work, the same as Cloudflare. 1/1 pass · 1 file
Notes
Not a mismatch.
Tests
  • synthetic--do-alarm-test › getSetDelete Pass
Source
packages/runtime-node/src/globals/cloudflare.ts:19
Unsupportedallow_eval_during_startupOn by default since 2025-06-01. eval() and new Function() work while the Worker starts and throw Code generation from strings disallowed for this context during a request.The table says true, and eval() and new Function() work at all times, including during requests. Orange behaves as if the experimental allow_insecure_inefficient_logged_eval flag is on, while the table says false for it. 1/3 pass · 2 files
Notes
Code that calls eval() in a handler works in Orange and fails on Cloudflare. worker-test testStartupEval and new-module-registry-startup-eval-test fail. experimental-eval-test passes.
Tests
  • api-tests--worker-test › testStartupEval AssertionError [ERR_ASSERTION]: Missing expected exception. Fail · Behavior differs
  • api-tests--new-module-registry-startup-eval-test › evalPermittedDuringStartupOnly AssertionError [ERR_ASSERTION]: Missing expected exception (EvalError). Fail · Behavior differs
  • api-tests--experimental-eval-test › evalTest Pass
Source
packages/runtime-node/src/globals/cloudflare.ts:92packages/runtime-node/src/globals/cloudflare.ts:115
Partialspec_compliant_dispatch_exceptionsOn by default from 2026-09-15, so off at 2026-09-03. When off, an exception in an event listener propagates out of dispatchEvent().The table says false, but listener exceptions do not propagate out of dispatchEvent(), as if the flag is on. 1/4 pass · 1 file
Notes
legacy-dispatch-exceptions-test, which sets no_spec_compliant_dispatch_exceptions, passes 1 of 4. Orange matches Cloudflare only for compatibility dates on or after 2026-09-15.
Not verified by a test
No saved test checks the spec-compliant side, so full agreement with it is not verified.
Tests
  • api-tests--legacy-dispatch-exceptions-test › dispatchEventPropagates AssertionError [ERR_ASSERTION]: Missing expected exception (Error). Fail · Behavior differs
  • api-tests--legacy-dispatch-exceptions-test › abortPropagates AssertionError [ERR_ASSERTION]: Missing expected exception (Error). Fail · Behavior differs
  • api-tests--legacy-dispatch-exceptions-test › messagePortLegacyRedispatch AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal: | + actual - expected | Fail · Behavior differs
  • api-tests--legacy-dispatch-exceptions-test › eventSourceLegacyError Pass
Source
packages/runtime-node/src/globals/cloudflare.ts:189
Partialdisallow_importable_envOff by default. When on, env and exports from cloudflare:workers are not populated.Off. The table says false, and import { env, exports } from "cloudflare:workers" always returns the live objects. Setting the flag does not change that. 1/3 pass · 3 files
Notes
The default side works. Both disable-importable tests fail because the flag has no effect.
Tests
  • api-tests--disable-importable-env-test › test 🍊 open-orange v0.0.1 · by rivet.dev | | Worker api-tests--disable-importable-env-test Fail · File fails at load
  • api-tests--disable-importable-exports-test › test AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: | + actual - expected | Fail · Behavior differs
  • api-tests--importable-exports-test › importableExports Pass
Source
packages/runtime-node/src/globals/cloudflare.ts:81packages/runtime-node/src/runtime.ts:145-146packages/runtime-node/src/runtime.ts:173-175
N/Anew_module_registryOff by default. When on, workerd resolves unbundled modules at runtime by URL.Off. The table says false. Orange always bundles the Worker with esbuild, and setting the flag only prints the ignored-flag warning. 0/2 pass · 2 files
Notes
Orange runs only the default side (flag off), which matches. The opt-in side is out of scope: upstream.json scores new-module-registry-test as not supported. Same status as the new_module_registry runtime entry.
Tests
  • api-tests--new-module-registry-test › complexModuleTest Build failed with 34 errors: | error: Cannot read directory "../../../..node_modules/zebra: not a \x00 valid URL": invalid argument | error: Cannot read directory "../../../..src/z Fail · Not supported
  • api-tests--new-module-registry-do-test › durableObjectTest AssertionError: Expected values to be strictly equal: | + actual - expected | Fail · Behavior differs
Source
packages/runtime-node/src/globals/cloudflare.ts:57src/build/bundle-worker.ts:323-355
N/Aenable_web_file_systemExperimental. Enables the Web File System API (navigator.storage, FileSystemFileHandle). Cloudflare does not deploy experimental flags.Off. The table says false. navigator.storage and the FileSystem handle classes are missing. 0/1 pass · 2 files
Notes
webfs-test, webfs-ts-test, and ts-webfs-writable-test are scored as not supported.
Tests
  • api-tests--webfs-test › webfsTest 🍊 open-orange v0.0.1 · by rivet.dev | | Worker api-tests--webfs-test Fail · Not supported
Source
packages/runtime-node/src/globals/cloudflare.ts:90packages/cloudflare-conformance/upstream.json:13-18
N/Artti_apiExperimental. Enables the workerd:rtti module. Cloudflare does not deploy experimental flags.Off. The table says false. Importing workerd:rtti prints a [bundle-warning] and throws No such module "workerd:rtti" when the importing module evaluates. 0/1 pass · 2 files
Notes
rtti-test fails at load.
Tests
  • api-tests--rtti-test › rtti-test 🍊 open-orange v0.0.1 · by rivet.dev | | Worker api-tests--rtti-test Fail · File fails at load
Source
packages/runtime-node/src/globals/cloudflare.ts:39src/build/bundle-worker.ts:319-322
N/Aunsafe_moduleExperimental. Enables the workerd:unsafe module. Cloudflare does not deploy experimental flags.Off. The table says false. Importing workerd:unsafe prints a [bundle-warning] and throws No such module "workerd:unsafe" when the importing module evaluates. 0/1 pass · 2 files
Notes
autogate-disabled-test is scored as test infrastructure because it imports workerd:unsafe.
Tests
  • api-tests--autogate-disabled-test › autogateDisabledTest 🍊 open-orange v0.0.1 · by rivet.dev | | Worker api-tests--autogate-disabled-test infra
Source
packages/runtime-node/src/globals/cloudflare.ts:43src/build/bundle-worker.ts:319-322
N/AexperimentalUnlocks experimental flags in workerd. Cloudflare does not accept it for deployed Workers.Off. The table says false. Setting it only prints the ignored-flag warning. 2 files
Unsupportedprecise_timersExperimental and off. Without it, Date.now() and performance.now() do not advance while code runs. They advance only after I/O.The table says false, but Date.now() and performance.now() are Node.js clocks that advance during synchronous code, as if the flag is on. 2 files
Notes
Timing code that measures CPU work reads real elapsed time in Orange and zero on Cloudflare.
Not verified by a test
No saved test checks clock advancement during synchronous code. The Cloudflare behavior is from the docs.
Source
packages/runtime-node/src/globals/cloudflare.ts:149packages/runtime-node/src/globals/native.ts:245-248 Cloudflare docs

Wrangler config

N/A$schemaPoints editors at the Wrangler JSON schema. Wrangler does not use it at runtime.Ignored, the same as Wrangler. 1 file
SupportedenvDefines named environments that override top-level keys. wrangler dev --env <name> selects one.orange dev --env <name> (or -e) passes the name to Wrangler's config reader, which applies the overrides. 2 files
Notes
Wrangler resolves inheritance, so non-inherited keys follow Wrangler's rules.
Source
src/commands/dev.ts:79-82src/config/load-wrangler.ts:1385-1387
SupportednameNames the Worker.Used as the Worker name. A service binding or Durable Object binding that names this Worker is local. Any other name loads as a stub. 3 files
Notes
The name also feeds version metadata through the normalized configuration.
Source
src/config/load-wrangler.ts:1432src/config/load-wrangler.ts:783-784src/config/load-wrangler.ts:653-667
N/Aaccount_idSelects the Cloudflare account for deploys and remote resources.Ignored. 1 file
SupportedmainThe Worker entrypoint module.Bundled with esbuild and loaded as the Worker. Config load fails with Wrangler configuration must resolve a Worker entrypoint when Wrangler resolves no main. 3 files
Notes
A positional script argument to orange dev overrides main, the same as Wrangler. main is optional when assets is set, as in Wrangler.
Source
src/config/load-wrangler.ts:1395-1404src/commands/dev.ts:117-122src/build/bundle-worker.ts:311-355
Rejectedfind_additional_modulesUploads files under base_dir that match rules as extra modules.When true, config load fails with Unsupported Wrangler configuration: find_additional_modules. 2 files
Notes
Orange always bundles the Worker into one module.
Source
src/config/load-wrangler.ts:567-569src/config/load-wrangler.ts:1408-1412
N/Apreserve_file_namesKeeps original file names for additional modules on upload.Ignored. 1 file
Notes
Only matters with find_additional_modules or rules, which Orange rejects.
Source
src/config/load-wrangler.ts:540-581 Cloudflare docs
N/Abase_dirThe directory where module rules are evaluated.Ignored. Orange does not pass it to esbuild. 1 file
Notes
Only matters with find_additional_modules or rules, which Orange rejects.
Source
src/build/bundle-worker.ts:326-355 Cloudflare docs
N/Aworkers_devPublishes the Worker on its workers.dev subdomain.Ignored. 1 file
N/Apreview_urlsPublishes preview URLs for each version.Ignored. 1 file
N/AroutesRoutes traffic for zone patterns and custom domains to the Worker.Ignored. Orange serves every request on its host and port. 1 file
N/ArouteA single route for the Worker.Ignored. Orange serves every request on its host and port. 1 file
UnsupportedtsconfigWrangler passes this tsconfig path to esbuild.Ignored. Orange does not pass it to esbuild, so esbuild reads the nearest tsconfig.json to each file instead. 1 file
Notes
Settings from a tsconfig at a custom path, such as paths aliases or jsx options, do not apply.
Workaround
Name the file tsconfig.json next to the source files.
Source
src/build/bundle-worker.ts:326-355
Unsupportedjsx_factorySets the JSX factory function for the Wrangler build. The default is React.createElement.Ignored. esbuild uses its default or the value from tsconfig.json. 1 file
Notes
The default matches Wrangler. Only a non-default value differs.
Workaround
Set jsxFactory in tsconfig.json.
Source
src/build/bundle-worker.ts:326-355
Unsupportedjsx_fragmentSets the JSX fragment function for the Wrangler build. The default is React.Fragment.Ignored. esbuild uses its default or the value from tsconfig.json. 1 file
Notes
The default matches Wrangler. Only a non-default value differs.
Workaround
Set jsxFragmentFactory in tsconfig.json.
Source
src/build/bundle-worker.ts:326-355
PartialmigrationsAn ordered list of Durable Object class migrations, each with a tag.Accepted when every migration has only tag, new_sqlite_classes, and new_classes. Durable Object classes need an initial creation migration, or config load fails with Durable Object classes require an initial new_sqlite_classes migration. 1 file
Notes
renamed_classes, deleted_classes, and transferred_classes fail config load. Duplicate tags and a class created by more than one migration fail config load. See the sub-field entries.
Source
src/config/load-wrangler.ts:946-983
Supportedmigrations[].new_sqlite_classesCreates SQLite-backed Durable Object classes.Creates the classes. Every Durable Object binding class must appear in one new_sqlite_classes or new_classes list, or config load fails with Durable Object class <name> is missing from new_sqlite_classes. 1/1 pass · 1 file
Notes
None.
Not verified by a test
No saved test loads a config with a missing new_sqlite_classes entry. The synthetic suite only shows SQLite classes work.
Tests
  • synthetic--do-storage-test › getPutOrdering Pass
Source
src/config/load-wrangler.ts:1018-1043
Rejectedmigrations[].renamed_classesRenames a Durable Object class and keeps its objects.Config load fails with Unsupported Durable Object migration fields: renamed_classes. 1 file
Rejectedmigrations[].deleted_classesDeletes a Durable Object class and its objects.Config load fails with Unsupported Durable Object migration fields: deleted_classes. 1 file
RejectedexportsDeclares Durable Object classes and entrypoints by class name, as an alternative to migrations.A non-empty exports object fails config load with Unsupported Wrangler configuration: exports. 2 files
Notes
None.
Workaround
Declare Durable Object classes with migrations and new_sqlite_classes.
Source
src/config/load-wrangler.ts:558-562src/config/load-wrangler.ts:1408-1412
Partialtriggers.cronsRuns the scheduled handler on cron schedules.Accepted. orange dev registers one Rivet cron job per expression in UTC and prints the next runs and a curl command for /cdn-cgi/local/scheduled. 4 files
Notes
Orange evaluates Cloudflare's cron syntax itself, including L, W, LW, #, and weekday 1 = Sunday. An expression that never matches or does not parse is skipped with a warning, where Cloudflare rejects it at deploy.
Source
src/config/load-wrangler.ts:583-609packages/runtime-node/src/runner.ts:1092-1131src/commands/dev.ts:279-287src/runtime/cron-triggers.test.ts:208-356
Rejectedtriggers.eventsRuns the Worker on Cloudflare events, such as Artifacts events.A non-empty list fails config load with Unsupported Wrangler configuration: triggers.events. 2 files
Unsupportedlimits.cpu_msSets the CPU time limit per invocation.Ignored. Orange enforces no CPU limit. 2 files
Unsupportedlimits.subrequestsSets the subrequest limit per invocation.Ignored. Orange enforces no subrequest limit. 1 file
Notes
See subrequest-limits.
Source
src/config/load-wrangler.ts:540-581
SupportedrulesModule rules that import Text, Data, and CompiledWasm modules by glob.Applies the configured rules, then Wrangler's default rules, with Wrangler's fallthrough handling. Text imports load as strings, Data as ArrayBuffers, and CompiledWasm as WebAssembly.Module. 3 files
Notes
Globs match the import specifier, as in Wrangler. ESModule and CommonJS rules are skipped because Orange bundles. Python rule types fail config load.
Source
src/config/load-wrangler.ts:611-642src/build/bundle-worker.ts:128-175src/commands/dev.test.ts:499-547
Supportedbuild.commandRuns a custom build command before Wrangler bundles the Worker.Runs the command through the shell in build.cwd before bundling. A non-zero exit stops orange dev with Running custom build <command> failed with exit code <code>. 4 files
Notes
There is no watch mode, so the command runs once per orange dev start.
Source
src/config/load-wrangler.ts:644-651src/commands/dev.ts:150-162src/commands/dev.test.ts:499-547src/commands/dev.test.ts:438-451
Supportedbuild.cwdThe directory for build.command.The directory build.command runs in, relative to the config file. Defaults to the config directory. 1 file
Unsupportedbuild.watch_dirDirectories that wrangler dev watches to rebuild.Ignored. orange dev does not watch files or rebuild. 1 file
Notes
Restart orange dev after a change.
Source
src/commands/dev.ts:180-288
Partialno_bundleSkips bundling and uploads the modules as written.Accepted. Orange still bundles the entry with esbuild, following the relative imports between the built modules. 2 files
Notes
Output from @cloudflare/vite-plugin, which sets no_bundle, runs. A module reached only through a computed import() path is not found.
Source
src/config/load-wrangler.ts:570-575src/commands/dev.test.ts:415-437
UnsupportedminifyMinifies the bundle.Ignored. The bundle is never minified. 1 file
Notes
Runtime behavior is the same except for function names and stack traces.
Source
src/build/bundle-worker.ts:326-355
Partialkeep_namesKeeps function and class names during minification. The default is true.Ignored. The bundle is not minified, so names are always kept. 1 file
Notes
The default matches. keep_names: false has no effect.
Source
src/build/bundle-worker.ts:326-355
N/Afirst_party_workerMarks an internal Cloudflare first-party Worker.Ignored. 1 file
N/AlogpushSends trace events to Workers Logpush.Ignored. 1 file
N/Aupload_source_mapsUploads source maps with the Worker.Ignored. The local bundle always has an inline source map. 1 file
Notes
Deploy-only key.
Source
src/build/bundle-worker.ts:351
N/AplacementSmart Placement runs the Worker near its back ends.Ignored. The Worker runs in the local process. 1 file
PartialassetsServes static assets, optionally through an ASSETS binding.orange dev serves the assets directory with Wrangler's router and asset Worker rules: html_handling, not_found_handling, run_worker_first patterns, .assetsignore, and assets-only Workers. 3 files
Notes
_headers and _redirects are not applied, and orange dev warns when they exist. The 25 MiB file and 100,000 file limits are not enforced. The directory is read on every request.
Source
src/config/load-wrangler.ts:1158-1203packages/runtime-node/src/bindings/assets/handler.tssrc/runtime/assets.test.ts:163-340
Rejectedlegacy_assetsThe legacy static assets key.Any value fails config load with Unsupported Wrangler configuration: legacy_assets. 1 file
RejectedsiteWorkers Sites static assets.Any value fails config load with Unsupported Wrangler configuration: site. 1 file
Rejectedpages_build_output_dirMarks a Pages project and its output directory.Any value fails config load with Unsupported Wrangler configuration: pages_build_output_dir. 1 file
N/AobservabilityEnables Workers Logs and traces with sampling.Ignored. Console output goes to the orange dev terminal. 1 file
N/AaccessConfigures Cloudflare Access authentication for the Worker.Ignored. Requests reach the Worker without Access. 1 file
Notes
Deploy-only key.
Not verified by a test
Whether access.dev changes wrangler dev behavior is not checked.
Source
src/config/load-wrangler.ts:540-581 Cloudflare docs
UnsupportedcacheEnables the Workers cache in front of the Worker and its cross-version behavior.Ignored. No cache runs in front of the Worker. 1 file
Notes
None.
Not verified by a test
The exact Cloudflare semantics of the cache key are from the schema description only.
Source
src/config/load-wrangler.ts:540-581 Cloudflare docs
N/Acompliance_regionSelects a compliance region for the deployed Worker.Ignored. 1 file
Unsupportedpython_modulesConfigures modules for Python Workers.Ignored. Orange does not run Python Workers. 1 file
Notes
A Python main cannot be bundled.
Not verified by a test
The failure mode for a Python main is not run.
Source
src/build/bundle-worker.ts:326-355
N/ApreviewsSettings for preview deployments made with wrangler preview.Ignored. 1 file
RejecteddefineReplaces global identifiers with constant values at build time.A non-empty define fails config load with Unsupported Wrangler configuration: define. 2 files
Partialsecrets.requiredLists the secrets the Worker needs. wrangler dev loads only these keys from .dev.vars or .env and warns about missing ones.Passed to Wrangler's dev-vars loader. A missing secret prints [config-warning] Missing required secrets: <names>. Add them to .dev.vars, .env, or set as environment variables. 2 files
Notes
The Worker still starts without the secret.
Not verified by a test
Whether Wrangler's loader filters .dev.vars keys to secrets.required is Wrangler behavior and is not run here.
Source
src/config/load-wrangler.ts:911-917src/commands/dev.ts:206-208
Partialqueues.consumersRuns the queue handler for messages on a queue.Accepted. Each consumer starts the delivery loop of its queue actor with max_batch_size, max_batch_timeout, max_retries, retry_delay, and dead_letter_queue. Unset settings take Cloudflare's production defaults: 10, 5 s, 3, and 0. 3 files
Notes
A value outside Cloudflare's range stops orange dev and names the queue. max_concurrency is ignored. See docs/modules/queues.mdx.
Source
src/config/load-wrangler.ts:1269-1299packages/runtime-node/src/runner.ts:904-910src/config/load-wrangler.test.ts:235-270
RejectedcloudchamberConfigures Cloudchamber container deployments.A non-empty object fails config load with Unsupported Wrangler configuration: cloudchamber. 1 file
AlternativecontainersConfigures Containers bound to Durable Object classes.Accepted with one warning. No container image runs. Sandbox classes from @cloudflare/sandbox, and other classes listed under containers, run on the ORANGE_SANDBOX_PROVIDER backend (default: local). 3 files
Notes
A listed class's ctx.container runs one sandbox per object, and start() takes only a Cloudflare Sandbox image: an image reference or Dockerfile that names cloudflare/sandbox. A class that containers does not list throws NotSupportedError from ctx.container. See do-ctx-container and docs/modules/sandbox.mdx.
Source
src/config/load-wrangler.ts:1664-1670src/config/load-wrangler.ts:578-598src/runtime/sandbox.test.ts:505-564
RejectedconnectOpens raw listening sockets that deliver connections to the Worker's connect handler.A non-empty list fails config load with Unsupported Wrangler configuration: connect. 2 files
Notes
A connect handler on an entrypoint still works over service bindings and ctx.exports.
Source
src/config/load-wrangler.ts:544-552packages/runtime-node/src/bindings/service.ts:330-361
Partialtail_consumersSends trace events to Tail Workers.Accepted. After each traced event, the Worker appends its TraceItem to a Rivet Durable Streams stream of each consumer, and an openorange:tail actor in the consumer Worker reads the stream and calls tail(). A consumer can be the Worker itself or another Worker of the orange dev session. 7 files
Notes
Delivery is at least once: the stream offset moves only after tail() returns. orange dev starts one Rivet Services process for the session. On a cluster, the namespace needs a Services deployment in the envoy pool services. handler-tail lists which events are traced. See docs/modules/tail-workers.mdx.
Source
src/config/load-wrangler.ts:510src/config/load-wrangler.ts:651-662src/config/load-wrangler.ts:690-698packages/runtime-node/src/runner.ts:340-385packages/runtime-node/src/runner.ts:914-924packages/runtime-node/src/internal-actors/tail.ts:19-26tests/tail-consumers.test.ts:25-122
Rejectedstreaming_tail_consumersSends streaming trace events to Tail Workers.A non-empty list fails config load with Unsupported Wrangler configuration: streaming_tail_consumers. 2 files
N/Asend_metricsControls Wrangler usage metrics.Ignored. Orange sends no usage metrics. 1 file
N/Adependencies_instrumentationControls npm dependency metadata sent on deploy.Ignored. 1 file
Unsupporteddev.ipThe address wrangler dev listens on.Ignored. orange dev listens on 127.0.0.1 unless --ip or --host is set. 2 files
Notes
The CLI flag works.
Workaround
Pass --ip.
Source
src/commands/dev.ts:49-56src/commands/dev.ts:87-90
Unsupporteddev.portThe port wrangler dev listens on.Ignored. orange dev listens on 8787 unless --port is set. 2 files
Notes
The CLI flag works.
Workaround
Pass --port.
Source
src/commands/dev.ts:49-56src/commands/dev.ts:91-94
Unsupporteddev.local_protocolServes wrangler dev over http or https.Ignored. orange dev serves HTTP only. --local-protocol https fails with OpenOrange dev currently supports only HTTP. 1 file
Notes
None.
Source
src/commands/dev.ts:95-100
Unsupporteddev.upstream_protocolSets the protocol of request.url in wrangler dev.Ignored. request.url always uses http and the incoming Host header. 1 file
Unsupporteddev.hostRewrites the host of request.url in wrangler dev.Ignored. request.url uses the incoming Host header. 1 file
Unsupporteddev.inspector_portThe port of the wrangler dev DevTools inspector.Ignored. orange dev opens no inspector port. 1 file
Notes
None.
Not verified by a test
Whether the runtime child process can be inspected another way is not checked.
Source
src/commands/dev.ts:49-124
UnsupportedaliasMaps module specifiers to other modules at build time.Ignored. Orange does not pass aliases to esbuild. An aliased import that does not resolve prints a [bundle-warning] and throws when the importing module evaluates. 2 files
N/Akeep_varsKeeps dashboard vars on deploy.Ignored. 1 file
N/AaddressesCreates Email Routing rules that send mail for these addresses to the Worker.Ignored. 2 files
Notes
Deploy-time routing. The email handler loads and never runs.
Source
src/config/load-wrangler.ts:540-581packages/runtime-node/src/runtime.ts:65-82
Rejectedunsafe (non-binding fields)unsafe.metadata and unsafe.capnp change the upload metadata or the workerd config directly.Any unsafe field other than bindings fails config load with Unsupported Wrangler configuration: unsafe. 2 files
Notes
unsafe.bindings is accepted. See the binding entries.
Source
src/config/load-wrangler.ts:534-538src/config/load-wrangler.ts:563-566
SupportedDurable Object class without a bindingA migrated class without a namespace binding is reachable through ctx.exports.Same. A class in new_sqlite_classes needs no durable_objects binding. 2 files
Notes
When durable_objects is set, it needs a bindings array, which can be empty.
Source
src/config/load-wrangler.ts:988-994packages/runtime-node/src/runtime.ts:168-172

Limits

SupportedStorage key sizeKey and value combined cannot exceed 2 MB.No Cloudflare limit. Rivet's applies: one write stores at most 134,217,728 bytes (128 MiB) of changed SQLite pages, so a key of 128 MiB or more throws a RangeError that names that limit. 3 files
SupportedStorage value sizeKey and value combined cannot exceed 2 MB.No Cloudflare limit. Rivet's applies: a key and value of 128 MiB or more together throw a RangeError that names Rivet's 128 MiB commit limit. An 8 MiB value works. 3 files
PartialKeys per multi-key put()No limit for SQLite-backed classes. At most 128 pairs for KV-backed classes.No limit for any class. 1 file
Notes
workerd checks the 128 limit only in its KV backend (actor-cache.c++), not in its SQLite backend. Orange stores new_classes in SQLite too, so it is looser for KV-backed classes.
Source
packages/runtime-node/src/bindings/durable-objects/storage.ts:88-93
PartialKeys per multi-key get()No limit for SQLite-backed classes. At most 128 keys for KV-backed classes.No limit for any class. 1 file
Notes
workerd checks the 128 limit only in its KV backend (actor-cache.c++), not in its SQLite backend. Orange stores new_classes in SQLite too, so it is looser for KV-backed classes.
Source
packages/runtime-node/src/bindings/durable-objects/storage.ts:88-93
PartialKeys per multi-key delete()No limit for SQLite-backed classes. At most 128 keys for KV-backed classes.No limit for any class. 1 file
Notes
workerd checks the 128 limit only in its KV backend (actor-cache.c++), not in its SQLite backend. Orange stores new_classes in SQLite too, so it is looser for KV-backed classes.
Source
packages/runtime-node/src/bindings/durable-objects/storage.ts:88-93
UnsupportedSQL statement lengthAt most 100 KB per statement (SQLITE_LIMIT_SQL_LENGTH 100000).No Orange check. SQLite's build limit applies. 1 file
Notes
Longer statements run on Orange and fail on Cloudflare.
Not verified by a test
Absence found by code search. The limits in the pinned RivetKit SQLite build are not checked.
Source
packages/runtime-node/src/bindings/durable-objects/storage.ts:609-634 Cloudflare docsCloudflare docs
UnsupportedSQL bound parameters per queryAt most 100 bound parameters per query.No Orange check. SQLite's build limit applies. 1 file
Notes
Queries with more than 100 parameters run on Orange and fail on Cloudflare.
Not verified by a test
Absence found by code search. The limits in the pinned RivetKit SQLite build are not checked.
Source
packages/runtime-node/src/bindings/durable-objects/storage.ts:626-629 Cloudflare docs
UnsupportedSQL columns per tableAt most 100 columns per table.No Orange check. SQLite's build limit applies. 1 file
Notes
None.
Not verified by a test
Absence found by code search. The limits in the pinned RivetKit SQLite build are not checked.
Source
packages/runtime-node/src/bindings/durable-objects/storage.ts:609-634 Cloudflare docs
UnsupportedSQL string or BLOB sizeEach string or BLOB value is at most 2 MB.No Orange check. SQLite's build limit applies. 1 file
Notes
None.
Not verified by a test
Absence found by code search. The limits in the pinned RivetKit SQLite build are not checked.
Source
packages/runtime-node/src/bindings/durable-objects/storage.ts:609-634 Cloudflare docs
UnsupportedSQL row sizeEach row is at most 2 MB.No Orange check. SQLite's build limit applies. 1 file
Notes
None.
Not verified by a test
Absence found by code search. The limits in the pinned RivetKit SQLite build are not checked.
Source
packages/runtime-node/src/bindings/durable-objects/storage.ts:609-634 Cloudflare docs
UnsupportedLIKE and GLOB pattern lengthAt most 50 bytes per LIKE or GLOB pattern.No Orange check. SQLite's build limit applies. 1 file
Notes
None.
Not verified by a test
Absence found by code search. The limits in the pinned RivetKit SQLite build are not checked.
Source
packages/runtime-node/src/bindings/durable-objects/storage.ts:609-634 Cloudflare docs
UnsupportedArguments per SQL functionThe documented limit is 32. workerd sets 127.No Orange check. SQLite's build limit applies. 1 file
Notes
None.
Not verified by a test
Absence found by code search. The limits in the pinned RivetKit SQLite build are not checked.
Source
packages/runtime-node/src/bindings/durable-objects/storage.ts:609-634 Cloudflare docs
UnsupportedStorage per Durable Object10 GB per object on Workers Paid. Writes past it fail.No limit. The object grows until the host disk is full. 1 file
Notes
None.
Not verified by a test
Absence found by code search.
Source
packages/runtime-node/src/bindings/durable-objects/storage.ts:704-706 Cloudflare docs
SupportedHibernatable WebSockets per objectAt most 32,768 accepted WebSockets per object.No limit. Accepted sockets are bounded by memory. 2 files
SupportedTags per WebSocketAt most 10 tags per hibernatable WebSocket.No limit. A socket with 20 tags works. 2 files
SupportedWebSocket tag lengthEach tag is at most 256 bytes.No limit. Tags of 300 bytes work. 2 files
SupportedWebSocket attachment sizeserializeAttachment() accepts at most 16 KiB of serialized data.No limit. A 64 KiB attachment works. 2 files
PartialHibernatable WebSocket event timeoutsetHibernatableWebSocketEventTimeout() accepts at most 604,800,000 ms (7 days).Up to 2,147,483,647 ms (about 24.8 days), the longest delay of a Node.js timer, which runs the timeout. A 20-day timeout works. 2 files
SupportedAuto-response request lengthThe auto-response request string is at most 2,048 bytes.No limit. A 4 KiB request works. 2 files
SupportedAuto-response response lengthThe auto-response response string is at most 2,048 bytes.No limit. A 4 KiB response works. 2 files
UnsupportedDurable Object WebSocket message sizeReceived WebSocket messages are at most 32 MiB.No Orange check. Rivet's WebSocket transport limit applies. 1 file
Notes
None.
Not verified by a test
Rivet's WebSocket message size limit is not checked.
Source
packages/runtime-node/src/globals/websocket.ts:507 Cloudflare docs
SupportedRPC payload sizeRPC values are at most 32 MiB.No Cloudflare limit. Rivet's applies: a Durable Object RPC call is one message to the Rivet Engine, which takes at most 32 MiB, with binary data in base64. A larger call throws a RangeError that names that limit. A 16 MiB value works. 3 files
Notes
Cloudflare's 32 MiB quota is not copied. Measured: 23.9 MiB of bytes works and 24 MiB is over the Engine's limit after base64.
Source
packages/runtime-node/src/internal/rivet-limits.ts:16-19packages/runtime-node/src/bindings/durable-objects/rpc/http.ts:147-161tests/beyond-cloudflare-quotas.test.ts:69-73
SupportedAlarm retriesA failing alarm handler retries up to 6 times.Same. 1 file
Notes
None.
Not verified by a test
Backoff timing is compared with workerd only, not with Cloudflare production.
Source
packages/runtime-node/src/bindings/durable-objects/alarm-storage.ts:27-29
SupportedblockConcurrencyWhile() nesting depthNesting deeper than 64 throws.No limit. Nesting 200 deep works. 2 files
Notes
Workerd's limit protects its native stack. Orange nests in JavaScript.
Source
packages/runtime-node/src/bindings/durable-objects/state.ts:207-208tests/beyond-cloudflare-quotas.test.ts:61-63
UnsupportedCPU time per invocation10 ms on Free. 30 s by default on Paid, configurable up to 5 minutes with limits.cpu_ms. Over the limit, the invocation fails.Not enforced. 1 file
Notes
A handler can run as long as it needs. Code that passes in Orange can exceed the Cloudflare limit.
Source
packages/runtime-node/src/runner.ts:951-1014 Cloudflare docs
UnsupportedMemory per isolate128 MB per isolate. Over the limit, the isolate is reset.Not enforced. 2 files
Notes
The runtime process uses the Node.js heap default.
Source
packages/runtime-node/src/runner.ts:951-1014src/runtime/spawn.ts:120-128 Cloudflare docs
UnsupportedSubrequests per invocation50 on Free and a higher configurable limit on Paid. Over the limit, fetch() throws.Not enforced. 1 file
Notes
fetch() and binding calls are never counted.
Not verified by a test
The current Paid default is from the docs page and is not restated here.
Source
packages/runtime-node/src/runner.ts:951-1014 Cloudflare docs
UnsupportedSimultaneous open connections6 per invocation. Extra fetch() calls and sockets wait for a free connection.Not enforced. 1 file
Notes
Orange opens as many connections in parallel as the code starts.
Source
packages/runtime-node/src/runner.ts:951-1014 Cloudflare docs
UnsupportedRequest body size100 MB on Free and Pro, 200 MB on Business, 500 MB on Enterprise. Larger requests get 413.Not enforced. The body streams into the Worker without a size check. 1 file
SupportedResponse body sizeNo limit on a streamed response body.No limit. The response streams to the client. 1 file
Notes
Cache limits do not apply because Orange has no cache.
Source
packages/runtime-node/src/runner.ts:951-1002 Cloudflare docs
UnsupportedURL length16 KB. Longer URLs get 414.Not enforced by Orange. Node.js counts the request line toward its header size limit. 1 file
Notes
See limit-request-headers.
Not verified by a test
The exact Node.js behavior for a long URL is not run.
Source
packages/runtime-node/src/runner.ts:953 Cloudflare docs
PartialRequest header size128 KB of request headers.Uses the Node.js HTTP server default of 16 KiB for the request line and headers. Larger requests get 431. 1 file
Notes
Orange is stricter than Cloudflare. Requests with 16 KiB to 128 KB of headers work on Cloudflare and fail in Orange.
Not verified by a test
The 16 KiB threshold is the Node.js default and is not run against Orange.
Source
packages/runtime-node/src/runner.ts:953 Cloudflare docs
UnsupportedEnvironment variable countAt most 64 variables on Free and 128 on Paid.Not enforced. Any number of vars load. 2 files
UnsupportedEnvironment variable sizeEach variable is at most 5 KB.Not enforced. Vars of any size load. 2 files
UnsupportedWorker size3 MB on Free and 10 MB on Paid, after compression. Larger Workers fail to deploy.Not enforced. Any bundle size loads. 1 file
UnsupportedWorker startup time1 s to parse and run the global scope. Over the limit, deploy fails.Not enforced. The global scope can run as long as it needs. 1 file
N/AWorkers per account100 on Free and 500 on Paid.Orange runs one Worker per process. 1 file
N/ACron triggers per account5 on Free and 250 on Paid.orange dev runs every configured cron. It has no per-account limit. 1 file
Notes
See config-cron-triggers.
Source
src/config/load-wrangler.ts:594-609 Cloudflare docs
UnsupportedConsole log sizeWorkers Logs truncates large log lines and caps log volume per invocation.Not enforced. console output goes to the orange dev terminal in full. 1 file
Notes
None.
Not verified by a test
The exact Cloudflare log size caps are not restated.
Source
src/commands/dev.ts:257-262 Cloudflare docs

What was run.

Each kind of result comes from its own recorded run. These are the commits and dates behind every number on this page.

  • workerd's suite ea40348 #10 at 028a0da with #11 and #7: Cloudflare quotas removed, quota-only tests cut. Limits revisions on #10 (Rivet limits only), with 9 quota-only workerd tests cut from the score. 292 workerd test files and 7 of OpenOrange's own: 1,774 + 77 tests. workerd v1.20260903.1 at b73ce3a, RivetKit 0.0.0-sqlite-sync-3-0-6-final.cf8679c. The run took 23 minutes. Nov 10, 20:08 UTC
  • Compared with ee0b731 #10 at ee0b731 on RivetKit 3.0.6, with #11 and #7, the saved run before, for what changed since. 2026-11-10
  • Probes e4c405f Each step run on workerd and on OpenOrange. RivetKit 0.0.0-sqlite-sync-3-0-1-final.5663d2f. 2026-11-10
  • Real projects 09b4d1d, 96efb7b, cb1ffb0, e4c405f 50 projects through orange dev. RivetKit 0.0.0-sqlite-sync-3-0-1-final.5663d2f. 2026-11-06
  • Emulated hibernation ee0b731 The 26 real-project steps that need hibernation, rerun. RivetKit 0.0.0-sqlite-sync-3-0-6-final.cf8679c. 2026-11-10
  • Examples e4c405f The runnable examples in the repository. 2026-11-05
  • Rivet Cloud — 6 projects, one run each on a Free cluster. 2026-11-05
  • Cloudflare's templates 6af8602 → c921bf3 Recorded by hand beside wrangler dev 4.129.0. 2026-10-20 → 2026-10-21

How this is scored.

The suite is workerd's own tests at v1.20260903.1, run on OpenOrange unchanged, plus 77 Durable Object tests OpenOrange adds. A Node.js test counts only when plain Node.js passes it, so 399 tests of workerd-specific behaviour are left out of every score. 19 tests the runner could not host are also left out.

A claim's status is set from its recorded results, never by hand. Probes run the same step on workerd and OpenOrange, so a row can show both. Real projects run at a pinned commit through orange dev, with changes listed on the row.

The matrix is maintained by hand and checked by tests: every source path it cites must exist and every test it cites must be in the latest run. Data and runner: cloudflare-conformance.

What each Cloudflare product runs on, its status and how to configure it: Bindings.

Not supported, counted as failures45 tests

  • new-module-registry-test Tests the opt-in new_module_registry flag: unbundled modules resolved as URLs at runtime. Orange always bundles the worker.
  • ts-webfs-writable-test Tests the Web File System API, which workerd only enables with the experimental enable_web_file_system flag. Cloudflare does not deploy experimental flags.
  • webfs-test Tests the Web File System API, which workerd only enables with the experimental enable_web_file_system flag. Cloudflare does not deploy experimental flags.
  • webfs-ts-test Tests the Web File System API, which workerd only enables with the experimental enable_web_file_system flag. Cloudflare does not deploy experimental flags.

Cloudflare quotas OpenOrange does not enforce, not counted9 tests

  • actor-block-concurrency-depth-test › main Fails blockConcurrencyWhile() nested at most 64 deep
  • blob-test › overLarge Fails A Blob of at most 128 MiB
  • global-scope-test › timeoutCount Fails At most 10,000 active timeouts per event
  • js-rpc-socket-streams-ts-test › stubDepthLimitTest Fails An RPC property path at most 64 deep
  • js-rpc-socket-test › stubDepthLimitTest Fails An RPC property path at most 64 deep
  • js-rpc-streams-ts-test › stubDepthLimitTest Fails An RPC property path at most 64 deep
  • js-rpc-test › stubDepthLimitTest Fails An RPC property path at most 64 deep
  • worker-loader-limits-test › codeSizeExceedsLimit Fails Dynamic Worker code of at most 64 MiB
  • worker-loader-limits-test › envSizeExceedsLimit Fails Dynamic Worker env of at most 1 MiB

Run yours.

Two commands. Your code does not change.

Built for serious scale.