Compatibility flags·续1

import { WorkflowEntrypoint, NonRetryableError } from "cloudflare:workers";

export class MyWorkflow extends WorkflowEntrypoint {
  async run(event, step) {
    await step.do("my-step", async () => {
      throw new NonRetryableError("custom error message");
      // Without this flag: error.message === "The execution of the Workflow instance was terminated, as a step threw an NonRetryableError and it was not handled"
      // With this flag: error.message === "custom error message"
    });
  }
}

With the workflows_preserve_non_retryable_error_message flag enabled, the original error message and name are preserved, making it easier to debug and handle specific error cases in your Workflow code.

Enhanced error serialization

Default as of 2026-04-21
Flag to enable enhanced_error_serialization
Flag to disable legacy_error_serialization

When enhanced_error_serialization is enabled, errors serialized using structuredClone() or V8 serialization support more error types and include own properties on the error object.

Note that when enabled, deserialization of errors will not preserve the original stack trace by default.

Previously, only basic Error types were serialized, and own properties added to error objects were lost during serialization.

Use an isolated PID namespace for containers

Default as of 2026-04-01
Flag to enable containers_pid_namespace
Flag to disable no_containers_pid_namespace

When containers_pid_namespace is set, containers will use an isolated PID namespace. The ENTRYPOINT of your container will have PID 1.

When unset, the container shares the PID namespace with the virtual machine (VM) containing the container. The ENTRYPOINT of your container will not have PID 1 and other processes running on the VM (that are not part of your container) will be visible.

Spec-compliant TextEncoderStream/TextDecoderStream backpressure

Default as of 2026-03-24
Flag to enable encoder_stream_spec_compliant_backpressure
Flag to disable no_encoder_stream_spec_compliant_backpressure

When encoder_stream_spec_compliant_backpressure is enabled, TextEncoderStream and TextDecoderStream use a readable-side high water mark of 0, as specified by the WHATWG Encoding Standard ↗︎.

With a high water mark of 0, the readable side starts with backpressure applied, so writes correctly block until a reader pulls. Previously, the high water mark defaulted to 1, which caused pull() to fire at startup, clearing backpressure before any write occurred.

Spec-compliant WritableStream writer behavior

Default as of 2026-03-24
Flag to enable writable_stream_spec_compliant_writer
Flag to disable no_writable_stream_spec_compliant_writer

When writable_stream_spec_compliant_writer is enabled, several WritableStream spec compliance issues around writer lock and release behavior are fixed to match the WHATWG Streams Standard ↗︎.

Enable global Performance classes

Default as of 2026-03-17
Flag to enable enable_global_performance_classes
Flag to disable disable_global_performance_classes

When enable_global_performance_classes is enabled, the following classes are available on the global scope: PerformanceEntry, PerformanceMark, PerformanceMeasure, PerformanceResourceTiming, PerformanceObserver, and PerformanceObserverEntryList.

These classes are also implicitly enabled by the enable_nodejs_perf_hooks_module flag.

This flag is automatically enabled for Workers using a compatibility date of 2026-03-17 or later when nodejs_compat is enabled.

Enable node:child_process module

Default as of 2026-03-17
Flag to enable enable_nodejs_child_process_module
Flag to disable disable_nodejs_child_process_module

The enable_nodejs_child_process_module flag enables the node:child_process module stub in Workers.

This flag is automatically enabled for Workers using a compatibility date of 2026-03-17 or later when nodejs_compat is enabled.

See the Node.js documentation ↗︎ for more details about the node:child_process API.

Enable node:perf_hooks module

Default as of 2026-03-17
Flag to enable enable_nodejs_perf_hooks_module
Flag to disable disable_nodejs_perf_hooks_module

The enable_nodejs_perf_hooks_module flag enables the node:perf_hooks module in Workers. This flag also implicitly enables global Performance classes (PerformanceEntry, PerformanceMark, PerformanceMeasure, PerformanceResourceTiming, PerformanceObserver, and PerformanceObserverEntryList).

This flag is automatically enabled for Workers using a compatibility date of 2026-03-17 or later when nodejs_compat is enabled.

See the Node.js documentation ↗︎ for more details about the node:perf_hooks API.

Enable node:readline module

Default as of 2026-03-17
Flag to enable enable_nodejs_readline_module
Flag to disable disable_nodejs_readline_module

The enable_nodejs_readline_module flag enables the node:readline module stub in Workers.

This flag is automatically enabled for Workers using a compatibility date of 2026-03-17 or later when nodejs_compat is enabled.

See the Node.js documentation ↗︎ for more details about the node:readline API.

Enable node:repl module

Default as of 2026-03-17
Flag to enable enable_nodejs_repl_module
Flag to disable disable_nodejs_repl_module

The enable_nodejs_repl_module flag enables the node:repl module stub in Workers.

This flag is automatically enabled for Workers using a compatibility date of 2026-03-17 or later when nodejs_compat is enabled.

See the Node.js documentation ↗︎ for more details about the node:repl API.

Enable node:tty module

Default as of 2026-03-17
Flag to enable enable_nodejs_tty_module
Flag to disable disable_nodejs_tty_module

The enable_nodejs_tty_module flag enables the node:tty module stub in Workers.

This flag is automatically enabled for Workers using a compatibility date of 2026-03-17 or later when nodejs_compat is enabled.

See the Node.js documentation ↗︎ for more details about the node:tty API.

Enable node:v8 module

Default as of 2026-03-17
Flag to enable enable_nodejs_v8_module
Flag to disable disable_nodejs_v8_module

The enable_nodejs_v8_module flag enables the node:v8 module stub in Workers.

This flag is automatically enabled for Workers using a compatibility date of 2026-03-17 or later when nodejs_compat is enabled.

See the Node.js documentation ↗︎ for more details about the node:v8 API.

Enable node:worker_threads module

Default as of 2026-03-17
Flag to enable enable_nodejs_worker_threads_module
Flag to disable disable_nodejs_worker_threads_module

The enable_nodejs_worker_threads_module flag enables the node:worker_threads module stub in Workers.

This flag is automatically enabled for Workers using a compatibility date of 2026-03-17 or later when nodejs_compat is enabled.

See the Node.js documentation ↗︎ for more details about the node:worker_threads API.

WebSocket standard binary type

Default as of 2026-03-17
Flag to enable websocket_standard_binary_type
Flag to disable no_websocket_standard_binary_type

This flag controls the default value of the binaryType property on WebSocket, which in turn controls how binary frames are delivered to the message event. With the flag active, binaryType defaults to "blob" and binary frames arrive as Blob ↗︎ objects, matching the WebSocket specification ↗︎ and standard browser behavior. Without the flag, binaryType defaults to "arraybuffer" and binary frames arrive as ArrayBuffer ↗︎, matching the runtime's historical behavior.

The binaryType property itself is available on every WebSocket regardless of the flag. Assigning a value overrides the default for that specific WebSocket:

const resp = await fetch("https://example.com", {
  headers: { Upgrade: "websocket" },
});
const ws = resp.webSocket;

// Opt back into ArrayBuffer delivery before calling accept().
ws.binaryType = "arraybuffer";
ws.accept();

ws.addEventListener("message", (event) => {
  // event.data is an ArrayBuffer for binary frames.
});

If you are not ready to migrate and want to keep ArrayBuffer as the default for every WebSocket in your Worker, add the no_websocket_standard_binary_type flag to your Wrangler configuration file.

This flag has no effect on the Durable Object hibernatable WebSocket webSocketMessage handler, which always receives binary data as ArrayBuffer.

Expose error codes in Queue operations

Default as of 2026-03-12
Flag to enable queue_expose_error_codes
Flag to disable no_queue_expose_error_codes

When queue_expose_error_codes is enabled, Queue operations will include detailed error information, including error codes and causes, making it easier to handle and diagnose queue-related errors programmatically.

WebSocket auto-reply to close

Default as of 2026-04-07
Flag to enable web_socket_auto_reply_to_close
Flag to disable web_socket_manual_reply_to_close

When a server sends a WebSocket Close frame, the Workers runtime now automatically sends a reciprocal Close frame and transitions readyState to CLOSED before firing the close event. This matches the WebSocket spec ↗︎ and browser behavior.

Previously, receiving a server-initiated Close frame left the WebSocket in CLOSING and required the application to call close() itself. With this flag active, you no longer need to call close() in your close event handler. The runtime handles the close handshake automatically.

const [client, server] = Object.values(new WebSocketPair());
server.accept();

server.addEventListener("close", (event) => {
  // readyState is already CLOSED — no need to call server.close().
  console.log(server.readyState); // WebSocket.CLOSED
  console.log(event.code); // 1000
  console.log(event.wasClean); // true
}, { once: true });

If you do still call close() inside the handler, the call is silently ignored. This means existing code that manually replies to Close frames will not break when you update your compatibility date.

The automatic close behavior can interfere with WebSocket proxying. When a Worker proxies between a client and a backend, the old behavior allowed the Worker to observe a backend Close frame without the runtime tearing down the connection, giving the Worker time to coordinate a clean close on the client side. To support this pattern, the accept() method now accepts an option allowHalfOpen. Call ws.accept({ allowHalfOpen: true }) to restore the old half-open behavior regardless of the compatibility flag.

const [client, server] = Object.values(new WebSocketPair());

// Opt into half-open mode for proxying
server.accept({ allowHalfOpen: true });

server.addEventListener("close", (event) => {
  // With allowHalfOpen true, readyState is still CLOSING here,
  // giving you time to coordinate the close on the other side.
  console.log(server.readyState); // WebSocket.CLOSING

// Manually close when ready.
  server.close(1000, "done");
}, { once: true });

Note that there is no corresponding option to the WebSocket constructor. WebSockets constructed with new WebSocket will always auto-reply to closes after this flag takes effect. WebSockets constructed this way are automatically "accepted", so there is no opportunity to pass the option to accept(). If you are creating a WebSocket with new WebSocket, but you need half-open behavior, you will need to switch to using fetch() instead.

// This does not allow half-open:
let ws = new WebSocket("wss://example.com");

// But you can do this instead:
let resp = await fetch("https://example.com", {
  headers: { "Upgrade": "websocket" }
});
if (!resp.webSocket) {
  throw new Error("WebSocket handshake not accepted");
}
let ws = resp.webSocket;
ws.accept({ allowHalfOpen: true });

For more information, refer to the WebSocket API documentation.

Dedicated CJK TextDecoder implementation

Default as of 2026-03-03
Flag to enable text_decoder_cjk_decoder
Flag to disable disable_text_decoder_cjk_decoder

When text_decoder_cjk_decoder is enabled, a dedicated CJK TextDecoder implementation is used for CJK encoding overrides and Big5 lead-byte handling, instead of the legacy ICU-only code path. This improves spec compliance for CJK text decoding.

Defer unhandled rejection processing to after microtask checkpoint

Default as of 2026-03-03
Flag to enable unhandled_rejection_after_microtask_checkpoint
Flag to disable no_unhandled_rejection_after_microtask_checkpoint

When unhandled_rejection_after_microtask_checkpoint is enabled, unhandledrejection event processing is deferred until the microtask checkpoint completes. This avoids misfires on multi-tick promise chains where a rejection handler is added in a later microtask.

Previously, unhandled rejection processing could fire prematurely before all microtasks in the current checkpoint had been processed, leading to false unhandledrejection events for promises that were actually handled.