Compatibility flags

Last updated Sep 18, 2026 Compatibility flags enable specific features. They can be useful if you want to help the Workers team test upcoming changes that are not yet enabled by default, or if you need to hold back a change that your code depends on but still want to apply other compatibility changes.

Compatibility flags will often have a date in which they are enabled by default, and so, by specifying a compatibility_date for your Worker, you can quickly enable all of these various compatibility flags up to, and including, that date.

Setting compatibility flags

You may provide a list of compatibility_flags, which enable or disable specific changes.

Via Wrangler

Compatibility flags can be set in a Worker's Wrangler configuration file.

This example enables the specific flag formdata_parser_supports_files, which is described below. As of the specified date, 2021-09-14, this particular flag was not yet enabled by default, but, by specifying it in compatibility_flags, we can enable it anyway. compatibility_flags can also be used to disable changes that became the default in the past.

{
    // Opt into backwards-incompatible changes through September 14, 2021.
    "compatibility_date": "2021-09-14",
    // Also opt into an upcoming fix to the FormData API.
    "compatibility_flags": [
        "formdata_parser_supports_files"
    ]
}
compatibility_date = "2021-09-14"
compatibility_flags = [ "formdata_parser_supports_files" ]

Via the Cloudflare Dashboard

Compatibility flags can be updated in the Workers settings on the Cloudflare dashboard ↗︎.

Via the Cloudflare API

Compatibility flags can be set when uploading a Worker using the Workers Script API or Workers Versions API in the request body's metadata field.

Node.js compatibility flag

Note

The nodejs_compat flag also enables nodejs_compat_v2 for compatibility dates from 2024-09-23 through 2026-08-03. The v2 flag improves Node.js compatibility by bundling additional polyfills and globals into your Worker. However, this improvement increases bundle size.

For compatibility dates through 2024-09-22, add nodejs_compat_v2 alongside nodejs_compat to turn on v2. For compatibility dates from 2024-09-23 through 2026-08-03, add no_nodejs_compat_v2 alongside nodejs_compat to use v1 only.

A growing subset of Node.js APIs are available directly as Runtime APIs, with no need to add polyfills to your own code.

For compatibility dates of 2026-08-04 or later, Workers and Pages projects enable both nodejs_compat and nodejs_compat_v2 by default. Built-in runtime APIs and polyfills are available without additional configuration. These flags are not used for these compatibility dates. Existing projects do not need to remove them when updating their compatibility date.

If your compatibility date is before 2026-08-04, add the nodejs_compat compatibility flag to your Wrangler configuration file to opt in:

{
    "compatibility_flags": [
        "nodejs_compat"
    ]
}
compatibility_flags = [ "nodejs_compat" ]

To turn off Node.js compatibility completely for a compatibility date of 2026-08-04 or later, remove the positive flags if present. Then add both no_nodejs_compat and no_nodejs_compat_v2. For configuration examples, refer to the Node.js compatibility flag.

For compatibility dates of 2026-08-04 or later, Workers enables both nodejs_compat and nodejs_compat_v2 by default. These flags are not used for these compatibility dates because the compatibility date enables the same behavior. Wrangler, Miniflare, the Cloudflare Vite plugin, and the Workers Vitest plugin ignore these redundant flags when starting the runtime. Existing projects do not need to remove them when updating their compatibility date. Omit them from new configurations.

To turn off Node.js compatibility completely for a compatibility date of 2026-08-04 or later, remove nodejs_compat and nodejs_compat_v2 if present. Then add both of the following flags:

{
    "compatibility_flags": [
        "no_nodejs_compat",
        "no_nodejs_compat_v2"
    ]
}
compatibility_flags = [ "no_nodejs_compat", "no_nodejs_compat_v2" ]

The Node.js AsyncLocalStorage API is a particularly useful feature for Workers. To enable only the AsyncLocalStorage API, use the nodejs_als compatibility flag.

{
    "compatibility_flags": [
        "nodejs_als"
    ]
}
compatibility_flags = [ "nodejs_als" ]

Flags history

Newest flags are listed first.

Remove Node.js 24.x end-of-life APIs

Default as of 2028-04-30
Flag to enable remove_nodejs_compat_eol_v24
Flag to disable add_nodejs_compat_eol_v24

When remove_nodejs_compat_eol_v24 is enabled, APIs that reached end-of-life in Node.js 24.x are removed.

This flag is automatically enabled when the remove_nodejs_compat_eol flag is enabled after 2028-04-30.

Remove Node.js 22.x end-of-life APIs

Default as of 2027-04-30
Flag to enable remove_nodejs_compat_eol_v22
Flag to disable add_nodejs_compat_eol_v22

When remove_nodejs_compat_eol_v22 is enabled, APIs that reached end-of-life in Node.js 22.x are removed.

This flag is automatically enabled when the remove_nodejs_compat_eol flag is enabled after 2027-04-30.

cache option does not override the origin's Cache-Control

Default as of 2026-11-17
Flag to enable cache_option_preserves_cache_control
Flag to disable cache_option_overrides_cache_control

When you enable the cache_option_preserves_cache_control compatibility flag, setting the cache property of the Request interface to no-cache or no-store no longer overrides the Cache-Control header of the origin's response when Cloudflare caches it.

Per the Fetch standard ↗︎, a request's cache mode controls how the cache may use a stored response. It does not control how the response may be cached:

  • no-cache forces Cloudflare's cache to revalidate with the origin.
  • no-store bypasses Cloudflare's cache.

Without this flag, cache: 'no-cache' also caches the response as if the origin had sent Cache-Control: no-cache, and cache: 'no-store' as if it had sent Cache-Control: no-store. For example, with cache: 'no-cache', a response the origin marked Cache-Control: no-store is cached as no-cache.

With this flag, the origin's Cache-Control is respected:

// Revalidates with the origin; the response is cached according to the origin's Cache-Control.
const response = await fetch("https://example.com", { cache: "no-cache" });

To override the origin's Cache-Control, omit the cache option and set cf.cacheControl instead:

const response = await fetch("https://example.com", {
    cf: { cacheControl: "no-cache" },
});

Backward error and close propagation in pipeTo()

Default as of 2026-11-17
Flag to enable pipe_to_backward_propagation
Flag to disable no_pipe_to_backward_propagation

When the pipe_to_backward_propagation flag is enabled, pipeTo() and pipeThrough() to a WritableStream created in JavaScript propagate errors and closure from the destination back to the source, as the WHATWG Streams Standard ↗︎ requires.

If the destination errors or closes while the pipe is waiting to read from the source, the pipe cancels the source (unless preventCancel is set), then rejects with the destination's error, or with a TypeError if the destination closed. If canceling the source fails, the pipe rejects with the cancel error instead.

Without the flag, the pipe still cancels the source in this case, but its promise resolves instead of rejecting. With preventCancel: true, the promise never settles. A failed cancel is not reported.

Durable Object I/O tasks prevent eviction

Default as of 2026-10-01
Flag to enable durable_object_io_tasks_prevent_eviction
Flag to disable durable_object_io_tasks_do_not_prevent_eviction

With the durable_object_io_tasks_prevent_eviction flag set, pending I/O keeps a Durable Object in memory after the client disconnects or drops its reference to the object. This includes service binding requests, Durable Object RPC calls, container.monitor(), and promises passed to this.ctx.waitUntil(). Each operation prevents eviction until it completes or for up to 15 minutes from when it starts, whichever comes first. Without this flag, a Durable Object with no connected client can be evicted while these operations are still pending. For more information, refer to Lifecycle of a Durable Object.

Web Crypto modern algorithms

Flag to enable webcrypto_modern_algorithms

Enables the Workers subset of the evolving Modern Algorithms in the Web Cryptography API ↗︎ draft. This subset includes:

  • ML-KEM and ML-DSA.
  • Key encapsulation and decapsulation methods.
  • getPublicKey() and SubtleCrypto.supports().
  • JSON Web Keys (JWKs) with the AKP key type.

Workers does not implement the full proposal. The API may change as the draft evolves. Refer to Supported algorithms for current support.

Spec-compliant dispatchEvent() exception handling

Default as of 2026-09-15
Flag to enable spec_compliant_dispatch_exceptions
Flag to disable no_spec_compliant_dispatch_exceptions

Per the DOM specification ↗︎, exceptions thrown by event listeners during dispatchEvent() should be reported (via the global error event and the console) but should not interrupt the dispatch or propagate to the dispatchEvent() caller. The remaining listeners for that event should still run.

The original Workers runtime implementation propagated the first listener exception and skipped all remaining listeners for that event. This affected the JS-visible dispatchEvent(), AbortSignal abort dispatch, and runtime-fired events on WebSocket, EventSource, and MessagePort.

When this flag is enabled, all of these event dispatch surfaces use the spec's report-and-continue semantics. A throwing listener's exception is reported on the global error event and logged to the console, but the dispatch continues through the remaining listeners. Top-level event delivery for legacy Service Worker syntax entry points (such as addEventListener("fetch", ...)) is not affected and always propagates exceptions.

Python 314 for Python Workers

Default as of 2026-09-08
Flag to enable python_workers_314

When this flag is set, Python 3.14 is used for Python Workers. Normally, you don't need to enable this flag manually, and the Python version is selected based on the compatibility date or your worker.

Throw On Not Implements TLS Options

Default as of 2026-06-16
Flag to enable throw_on_not_implemented_tls_options
Flag to disable no_throw_on_not_implemented_tls_options

When enabled, passing unsupported TLS options (e.g. checkServerIdentity) to tls.connect() or new TLSSocket() throws ERR_OPTION_NOT_IMPLEMENTED instead of silently ignoring them

Process .pth files for Python Workers

Default as of 2026-05-26
Flag to enable python_process_pth_files
Flag to disable disable_python_process_pth_files

When the python_process_pth_files flag is set, Python Workers process .pth files in the python_modules/ directory during startup by calling site.addsitedir() ↗︎ on it. This lets packages extend sys.path declaratively, for example to add subdirectories or register import hooks. Without this flag, .pth files in python_modules/ are ignored.

This flag also moves the top-level entropy context managers required by some packages out of the runtime and into workers-py ↗︎.

You must use workers-py version 1.1.3 or later when this flag is set.

Node.js diagnostics_channel hasSubscribers getter

Default as of 2026-05-19
Flag to enable diagnostics_channel_has_subscribers_getter
Flag to disable no_diagnostics_channel_has_subscribers_getter

When diagnostics_channel_has_subscribers_getter is enabled, Channel.hasSubscribers and TracingChannel.hasSubscribers from node:diagnostics_channel become read-only getter properties that evaluate directly to a boolean, matching Node.js behavior.

Previously, hasSubscribers was registered as a method, requiring users to call ch.hasSubscribers() with parentheses. With this flag enabled, ch.hasSubscribers returns a boolean without a function call, consistent with the Node.js documentation ↗︎.

This flag requires nodejs_compat to be enabled.

Workflows preserve NonRetryableError message

Default as of 2026-05-14
Flag to enable workflows_preserve_non_retryable_error_message
Flag to disable workflows_replace_non_retryable_error_message

When enabled, if a Workflow step throws a NonRetryableError, the error message and name properties are preserved on the thrown exception instead of being replaced with a generic termination string.

Previously, throwing a NonRetryableError with a custom message would result in the original error message being lost and replaced with "The execution of the Workflow instance was terminated, as a step threw an NonRetryableError and it was not handled":