Cloudflare Docs
View GitHub RSS feed
Visit Workers on GitHub
Set theme to dark (⇧+D)

Compatibility dates

Cloudflare regularly updates the Workers runtime. These updates apply to all Workers globally and should never cause a Worker that is already deployed to stop functioning. Sometimes, though, some changes may be backwards-incompatible. In particular, there might be bugs in the runtime API that existing Workers may inadvertently depend upon. Cloudflare implements bug fixes that new Workers can opt into while existing Workers will continue to see the buggy behavior to prevent breaking deployed Workers.

Compatibility dates (and flags) are how you, as a developer, opt into these changes. By specifying a compatibility_date in your wrangler.toml file, that Worker enables all changes that were made before the given date.

Compatibility dates can only be set via your wrangler.toml file and by running npx wrangler deploy.

# (in wrangler.toml)
# Opt into backwards-incompatible changes through April 5, 2022.
compatibility_date = "2022-04-05"

When you start your project, you should always set compatibility_date to the current date. You should occasionally update the compatibility_date field. When updating, you should refer to this page to find out what has changed, and you should be careful to test your Worker to see if the changes affect you, updating your code as necessary. The new compatibility date takes effect when you next run the npx wrangler deploy command.

There is no need to update your compatibility_date if you do not want to. The Workers runtime will support old compatibility dates forever. If, for some reason, Cloudflare finds it is necessary to make a change that will break live Workers, Cloudflare will actively contact affected developers. That said, Cloudflare aims to avoid this if at all possible.

However, even though you do not need to update the compatibility_date field, it is a good practice to do so for two reasons:

  1. Sometimes, new features can only be made available to Workers that have a current compatibility_date. To access the latest features, you need to stay up-to-date.
  2. Generally, other than this page, the Workers documentation may only describe the current compatibility_date, omitting information about historical behavior. If your Worker uses an old compatibility_date, you will need to continuously refer to this page in order to check if any of the APIs you are using have changed.

​​ Compatibility flags

In addition to setting a compatibility_date in your wrangler.toml file, you may also provide a list of compatibility_flags, which enable or disable specific changes.

# (in wrangler.toml)
# 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" ]

This example enabled 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 specifying it in this way enables it anyway. compatibility_flags can also be used to disable changes that became the default in the past.

Most developers will not need to use compatibility_flags; instead, Cloudflare recommends only specifying compatibility_date. compatibility_flags 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.

​​ Node.js compatibility flag

A growing subset of Node.js APIs are available directly as Runtime APIs, with no need to add polyfills to your own code. To enable these APIs in your Worker, add the nodejs_compat compatibility flag to your wrangler.toml:

compatibility_flags = [ "nodejs_compat" ]

As additional Node.js APIs are added, they will be made available under the nodejs_compat compatibility flag. Unlike most other compatibility flags, we do not expect the nodejs_compat to become active by default at a future date.

​​ Change history

Newest changes are listed first.

​​ WebSocket Compression

Default as of 2023-08-15
Flag to enable web_socket_compression
Flag to disable no_web_socket_compression

The Workers runtime did not support WebSocket compression when the initial WebSocket implementation was released. Historically, the runtime has stripped or ignored the Sec-WebSocket-Extensions header – but is now capable of fully complying with the WebSocket Compression RFC. Since many clients are likely sending Sec-WebSocket-Extensions: permessage-deflate to their Workers today (new WebSocket(url) automatically sets this in browsers), we have decided to maintain prior behavior if this flag is absent.

If the flag is present, the Workers runtime is capable of using WebSocket Compression on both inbound and outbound WebSocket connections.

Like browsers, calling new WebSocket(url) in a Worker will automatically set the Sec-WebSocket-Extensions: permessage-deflate header. If you are using the non-standard fetch() API to obtain a WebSocket, you can include the Sec-WebSocket-Extensions header with value permessage-deflate and include any of the compression parameters defined in RFC-7692.

​​ Strict crypto error checking

Default as of 2023-08-01
Flag to enable strict_crypto_checks
Flag to disable no_strict_crypto_checks

Perform additional error checking in the Web Crypto API to conform with the specification and reject possibly unsafe key parameters:

  • For RSA key generation, key sizes are required to be multiples of 128 bits as boringssl may otherwise truncate the key.
  • The size of imported RSA keys must be at least 256 bits and at most 16384 bits, as with newly generated keys.
  • The public exponent for imported RSA keys is restricted to the commonly used values [3, 17, 37, 65537].
  • In conformance with the specification, an error will be thrown when trying to import a public ECDH key with non-empty usages.

​​ Strict compression error checking

Default as of 2023-08-01
Flag to enable strict_compression_checks
Flag to disable no_strict_compression_checks
Perform additional error checking in the Compression Streams API and throw an error if a DecompressionStream has trailing data or gets closed before the full compressed data has been provided.

​​ Use a spec compliant URL implementation in redirects

Default as of 2023-03-14
Flag to enable response_redirect_url_standard
Flag to disable response_redirect_url_original
Change the URL implementation used in Response.redirect() to be spec-compliant (WHATWG URL Standard).

​​ Dynamic Dispatch Exception Propagation

Default as of 2023-03-01
Flag to enable dynamic_dispatch_tunnel_exceptions
Flag to disable dynamic_dispatch_treat_exceptions_as_500
Previously, when using Workers for Platforms’ dynamic dispatch API to send an HTTP request to a user Worker, if the user Worker threw an exception, the dynamic dispatch Worker would receive an HTTP 500 error with no body. When the dynamic_dispatch_tunnel_exceptions compatibility flag is enabled, the exception will instead propagate back to the dynamic dispatch Worker. The fetch() call in the dynamic dispatch Worker will throw the same exception. This matches the similar behavior of service bindings and Durable Objects.

​​ Streams Constructors

Default as of 2022-11-30
Flag to enable streams_enable_constructors
Flag to disable streams_disable_constructors
Adds the work-in-progress new ReadableStream() and new WritableStream() constructors backed by JavaScript underlying sources and sinks.

​​ Compliant TransformStream constructor

Default as of 2022-11-30
Flag to enable transformstream_enable_standard_constructor
Flag to disable transformstream_disable_standard_constructor
Previously, the new TransformStream() constructor was not compliant with the Streams API standard. Use the transformstream_enable_standard_constructor to opt-in to the backwards-incompatible change to make the constructor compliant. Must be used in combination with the streams_enable_constructors flag.

​​ CommonJS modules do not export a module namespace

Default as of 2022-10-31
Flag to enable export_commonjs_default
Flag to disable export_commonjs_namespace
CommonJS modules were previously exporting a module namespace (an object like { default: module.exports }) rather than exporting only the module.exports. When this flag is enabled, the export is fixed.

​​ Do not throw from async functions

Default as of 2022-10-31
Flag to enable capture_async_api_throws
Flag to disable do_not_capture_async_api_throws
The capture_async_api_throws compatibility flag will ensure that, in conformity with the standards API, async functions will only ever reject if they throw an error. The inverse do_not_capture_async_api_throws flag means that async functions which contain an error may throw that error synchronously rather than rejecting.

​​ New URL parser implementation

Default as of 2022-10-31
Flag to enable url_standard
Flag to disable url_original

The original Workers URL API implementation is not fully compliant with the WHATWG URL Standard. Cloudflare has added a new implementation that is fully compliant. However, since the new implementation is not completely backwards compatible, it is disabled by default. Use the url_standard flag to enable the new implementation.

​​ R2 bucket list respects the include option

Default as of 2022-08-04
Flag to enable r2_list_honor_include
With the r2_list_honor_include flag set, the include argument to R2 list options is honored. With an older compatability date and without this flag, the include argument behaves implicitly as include: ["httpMetadata", "customMetadata"].

​​ Do not substitute null on TypeError

Default as of 2022-06-01
Flag to enable dont_substitute_null_on_type_error
Flag to disable substitute_null_on_type_error
There was a bug in the runtime that meant that when being passed into built-in APIs, invalid values were sometimes mistakenly coalesced with null. Instead, a TypeError should have been thrown. The dont_substitute_null_on_type_error fixes this behavior so that an error is correctly thrown in these circumstances.

​​ Minimal subrequests

Default as of 2022-04-05
Flag to enable minimal_subrequests
Flag to disable no_minimal_subrequests

With the minimal_subrequests flag set, fetch() subrequests sent to endpoints on the Worker’s own zone (also called same-zone subrequests) have a reduced set of features applied to them. In general, these features should not have been initially applied to same-zone subrequests, and very few user-facing behavior changes are anticipated. Specifically, Workers might observe the following behavior changes with the new flag:

  • Response bodies will not be opportunistically gzipped before being transmitted to the Workers runtime. If a Worker reads the response body, it will read it in plaintext, as has always been the case, so disabling this prevents unnecessary decompression. Meanwhile, if the Worker passes the response through to the client, Cloudflare’s HTTP proxy will opportunistically gzip the response body on that side of the Workers runtime instead. The behavior change observable by a Worker script should be that some Content-Encoding: gzip headers will no longer appear.
  • Automatic Platform Optimization may previously have been applied on both the Worker’s initiating request and its subrequests in some circumstances. It will now only apply to the initiating request.
  • Link prefetching will now only apply to the Worker’s response, not responses to the Worker’s subrequests.
Default as of 2022-03-21
Flag to enable global_navigator
Flag to disable no_global_navigator
With the global_navigator flag set, a new global navigator property is available from within Workers. Currently, it exposes only a single navigator.userAgent property whose value is set to 'Cloudflare-Workers'. This property can be used to reliably determine whether code is running within the Workers environment.

​​ Do not use the Custom Origin Trust Store for external subrequests

Default as of 2022-03-08
Flag to enable no_cots_on_external_fetch
Flag to disable cots_on_external_fetch
The no_cots_on_external_fetch flag disables the use of the Custom Origin Trust Store when making external (grey-clouded) subrequests from a Cloudflare Worker.

​​ Setters/getters on API object prototypes

Default as of 2022-01-31
Flag to enable workers_api_getters_setters_on_prototype
Flag to disable workers_api_getters_setters_on_instance

Originally, properties on Workers API objects were defined as instance properties as opposed to prototype properties. This broke subclassing at the JavaScript layer, preventing a subclass from correctly overriding the superclass getters/setters. This flag controls the breaking change made to set those getters/setters on the prototype template instead.

This changes applies to:

  • AbortSignal
  • AbortController
  • Blob
  • Body
  • DigestStream
  • Event
  • File
  • Request
  • ReadableStream
  • ReadableStreamDefaultReader
  • ReadableStreamBYOBReader
  • Response
  • TextDecoder
  • TextEncoder
  • TransformStream
  • URL
  • WebSocket
  • WritableStream
  • WritableStreamDefaultWriter

​​ Durable Object stub.fetch() requires a full URL

Default as of 2021-11-10
Flag to enable durable_object_fetch_requires_full_url
Flag to disable durable_object_fetch_allows_relative_url
Originally, when making a request to a Durable Object by calling stub.fetch(url), a relative URL was accepted as an input. The URL would be interpreted relative to the dummy URL http://fake-host, and the resulting absolute URL was delivered to the destination object’s fetch() handler. This was a mistake — full URLs were meant to be required. This flag makes full URLs required.

​​ fetch() improperly interprets unknown protocols as HTTP

Default as of 2021-11-10
Flag to enable fetch_refuses_unknown_protocols
Flag to disable fetch_treats_unknown_protocols_as_http

Originally, if the fetch() function was passed a URL specifying any protocol other than http: or https:, it would silently treat it as if it were http:. For example, fetch() would appear to accept ftp: URLs, but it was actually making HTTP requests instead.

Note that Cloudflare Workers supports a non-standard extension to fetch() to make it support WebSockets. However, when making an HTTP request that is intended to initiate a WebSocket handshake, you should still use http: or https: as the protocol, not ws: nor wss:.

The ws: and wss: URL schemes are intended to be used together with the new WebSocket() constructor, which exclusively supports WebSocket. The extension to fetch() is designed to support HTTP and WebSocket in the same request (the response may or may not choose to initiate a WebSocket), and so all requests are considered to be HTTP.

​​ Streams BYOB reader detaches buffer

Default as of 2021-11-10
Flag to enable streams_byob_reader_detaches_buffer
Flag to disable streams_byob_reader_does_not_detach_buffer

Originally, the Workers runtime did not detach the ArrayBuffers from user-provided TypedArrays when using the BYOB reader’s read() method, as required by the Streams spec, meaning it was possible to inadvertently reuse the same buffer for multiple read() calls. This change makes Workers conform to the spec.

User code should never try to reuse an ArrayBuffer that has been passed into a BYOB reader’s read() method. Instead, user code can reuse the ArrayBuffer backing the result of the read() promise, as in the example below.

// Consume and discard `readable` using a single 4KiB buffer.
let reader = readable.getReader({ mode: "byob" });
let arrayBufferView = new Uint8Array(4096);
while (true) {
let result = await;
if (result.done) break;
// Optionally something with `result` here.
// Re-use the same memory for the next `read()` by creating
// a new Uint8Array backed by the result's ArrayBuffer.
arrayBufferView = new Uint8Array(result.value.buffer);

The more recently added extension method readAtLeast() will always detach the ArrayBuffer and is unaffected by this feature flag setting.

​​ FormData parsing supports File

Default as of 2021-11-03
Flag to enable formdata_parser_supports_files
Flag to disable formdata_parser_converts_files_to_strings

The FormData API is used to parse data (especially HTTP request bodies) in multipart/form-data format.

Originally, the Workers runtime’s implementation of the FormData API incorrectly converted uploaded files to strings. Therefore, formData.get("filename") would return a string containing the file contents instead of a File object. This change fixes the problem, causing files to be represented using File as specified in the standard.

​​ Experimental changes

These changes can be enabled via compatibility_flags, but are not yet scheduled to become default on any particular date.

​​ HTMLRewriter handling of <esi:include>

Default as of TBD
Flag to enable html_rewriter_treats_esi_include_as_void_tag
Flag to disable TBD

The HTML5 standard defines a fixed set of elements as void elements, meaning they do not use an end tag: <area>, <base>, <br>, <col>, <command>, <embed>, <hr>, <img>, <input>, <keygen>, <link>, <meta>, <param>, <source>, <track>, and <wbr>.

HTML5 does not recognize XML self-closing tag syntax. For example, <script src="foo.js" /> does not specify a script element with no body. A </script> ending tag is still required. The /> syntax simply is not recognized by HTML5 at all and it is treated the same as >. However, many developers still like to use this syntax, as a holdover from XHTML, a standard which failed to gain traction in the early 2000’s.

<esi:include> and <esi:comment> are two tags that are not part of the HTML5 standard, but are instead used as part of Edge Side Includes, a technology for server-side HTML modification. These tags are not expected to contain any body and are commonly written with XML self-closing syntax.

HTMLRewriter was designed to parse standard HTML5, not ESI. However, it would be useful to be able to implement some parts of ESI using HTMLRewriter. To that end, this compatibility flag causes HTMLRewriter to treat <esi:include> and <esi:comment> as void tags, so that they can be parsed and handled properly.