compatibility dates
why wasm breaks silently and how compatibility_date fixes it
compatibility dates
cloudflare workers pin runtime behavior to a specific date. javascript apis added after your compatibility_date are unavailable — failures are often silent.
why some apis are gated
workers run in v8 isolates where deterministic execution matters. WeakRef and FinalizationRegistry let code observe garbage collection — a fundamentally nondeterministic process. cloudflare disabled both by default to prevent gc-dependent behavior in a serverless model where isolation and consistency are critical.
the enable_weak_ref flag opts into the nondeterminism tradeoff. enables both apis together — WeakRef alone is safer but the two are almost always used as a pair.
| feature | minimum date | flag |
|---|---|---|
WeakRef |
2025-05-05 | enable_weak_ref |
FinalizationRegistry |
2025-05-05 | enable_weak_ref |
why wasm runtimes need them
wasm modules that bridge to javascript need to track host object lifecycles. when a js-side wrapper gets garbage collected, the wasm side needs to clean up the corresponding resource. FinalizationRegistry handles this — register a callback when the wrapper is created, clean up when it's collected.
runtimes that depend on this:
- teavm (elk wasm) — jso interop, weak reference tracking, string finalization
- tinygo — wasi stubs with host object bridging
- any wasm module using weak reference tracking for js/wasm boundary management
without the flag, registrations silently fail. the module loads, init appears to succeed, but every function call throws.
issue i had
the tools worker had compatibility_date = "2024-12-01". go wasm loaded without error but goEncrypt() / goDecrypt() threw — init silently failed because the runtime lacked FinalizationRegistry. same failure mode affected elk wasm for architecture diagram layouts.
no deploy-time warning. no init-time error. failure only at call time.
# wrangler.toml — before
compatibility_date = "2024-12-01"
# after
compatibility_date = "2025-06-01"alternatively, pin the flag without bumping the full date:
compatibility_flags = ["enable_weak_ref"]