zudo-cloudflare-wisdom

Type to search...

to open search from anywhere

Compatibility Dates

CreatedApr 4, 2026UpdatedMay 28, 2026Takeshi Takatsudo

Understanding and managing Cloudflare compatibility dates

What Are Compatibility Dates?

The compatibility_date in wrangler.toml pins your Worker to a specific version of the Cloudflare Workers runtime. This prevents breaking changes from affecting your deployed code.

compatibility_date = "2024-12-01"

How They Work

  • Cloudflare introduces runtime changes behind flags tied to dates
  • Setting a date enables all changes up to and including that date
  • Your code uses the same runtime behavior until you update the date
  • New projects should use a recent date

When to Update

Update the compatibility date when:

  • You are actively working on the project
  • You want access to new runtime features
  • The Cloudflare docs recommend a minimum date for a feature you need

⚠️ Warning

Updating the compatibility date can change runtime behavior. Test thoroughly after updating, especially if jumping across many months.

Compatibility Flags

For granular control, you can enable or disable specific flags:

compatibility_date = "2024-12-01"
compatibility_flags = ["nodejs_compat"]

Common flags:

FlagDescription
nodejs_compatEnable Node.js built-in module support
streams_enable_constructorsEnable constructable Streams API

When You Actually Need nodejs_compat

nodejs_compat is not optional decoration. If your bundle (or an adapter such as zfb’s _worker.js wrapper) imports a Node.js built-in like node:async_hooks (AsyncLocalStorage), node:crypto, or node:buffer, then omitting the flag makes wrangler refuse to load the worker. That is a deploy-time failure, not a graceful runtime fallback — the deploy stops; you do not get a working worker that silently degrades.

compatibility_date = "2024-12-01"
compatibility_flags = ["nodejs_compat"]

The concrete trigger is the AsyncLocalStorage per-request-context pattern used by the SSR bindings adapter recipe: it threads Cloudflare bindings (KV, D1, R2, env) into a getCloudflareContext()-style accessor via node:async_hooks. The moment that import lands in your bundle, nodejs_compat becomes a hard requirement for every deploy of that worker.

⚠️ Warning

This is a build/deploy-time gate, not a runtime one. You will not discover it from a passing local test that never imports the Node built-in — you discover it when wrangler refuses to load the worker during deployment. If a worker depends on node:* modules, keep nodejs_compat in its compatibility_flags permanently.