Cloudflare Workers Compatibility Checker for npm
Check which npm packages run on Cloudflare Workers, which need nodejs_compat and which will not run, then copy the compatibility_date and flags.
- Reads the npm registry
- Reads jsDelivr file lists
- Reads jsDelivr
Checked
01Tool
Tool
Paste a package.json or a list of package names to see which run on Cloudflare Workers as they are, which need Node.js compatibility, and which will not run, with the wrangler.jsonc settings the result needs.
What compatibility_date and flags do
compatibility_date- Picks the version of the Workers runtime your Worker runs on: every change up to that day applies. Cloudflare supports old dates forever and recommends today's date for a new project.
compatibility_flags- Turn a single change on before its default date, or off after it.
nodejs_compat- Turns on the Node.js APIs built into the runtime, plus Wrangler's polyfills for the rest. From 2026-08-04, the date turns it on and the flag does nothing.
enable_nodejs_…_module- Turns on one Node.js module before the date it ships by default, such as enable_nodejs_fs_module.
no_nodejs_compat- From 2026-08-04, turning Node.js compatibility off takes both no_nodejs_compat and no_nodejs_compat_v2.
02Guide
How it works
How the checker reads a package
Nothing leaves the page until you press Check packages. Then, for each package, the checker asks the npm registry for the newest version your range allows, the same one a fresh install picks, and asks jsDelivr for that version's file list.
From the file list and the package's manifest it finds the file Wrangler would bundle. Wrangler builds with esbuild and sets the workerd, worker and browser conditions, so in a package's exports the checker takes the first key among those, import and default, in the order the package lists them. A package without exports falls back to its browser, module and main fields, in that order, and a browser map that swaps a file or switches a module off is applied too.
It then reads that entry file and the files it imports inside the same package, up to a cap, and collects every import, export … from, require() and import() with a fixed string. A require inside a try block or a dynamic import() counts as optional, because a package that guards a Node.js import usually has a fallback.
Before reading any code, it looks for signs of native code: a .node file or binding.gyp in the package, an install script that runs node-gyp or prebuild-install, a dependency on a native loader such as node-gyp-build, a set of per-platform binary packages in optionalDependencies, or an os or cpu list that limits where it installs.
What the five results mean
Runs as is. The entry files import no Node.js built-in and nothing native turned up. Many packages written for browsers or for several runtimes land here, and some ship a build just for Workers under the workerd or worker condition.
Needs Node.js compatibility. The package imports at least one Node.js module. The result says which ones, in which file, and the first compatibility date on which all of them work.
Loads, some calls fail. The package also imports a module that Workers ship only as a stub, such as node:child_process. It loads, but whatever calls into that module throws. That can be one transport you never use, as with nodemailer's sendmail, or the whole point of the package, as with execa.
Will not run. The package needs native code, or drives a browser on the same machine as Puppeteer and Playwright do, so no compatibility date or flag will make it work. The Workers option beside it points to the Cloudflare product that covers the same job where one is well known.
Could not tell. npm does not know the package or version, the version is local such as workspace: or file:, the package has no entry file to import, its entry file is too large to read here, or it is a Nuxt module.
The compatibility date and nodejs_compat
compatibility_date pins the version of the Workers runtime your Worker runs on, and compatibility_flags turn single changes on or off around it. Node.js support is one of those changes, and several Node.js modules arrived on later dates, so the checker works out the earliest date that covers every module the packages import.
For a new project, the settings use today's date, which already turns Node.js compatibility on, so they need no flag. A project that stays on a date from before that default needs the flag, like this:
{
"compatibility_date": "2026-03-17",
"compatibility_flags": ["nodejs_compat"],
}
If you keep an older date, type it in. The checker keeps it when it is new enough, adds nodejs_compat when the date needs it, and otherwise says which date to move to, or which enable_nodejs_…_module flags would keep your date working instead.
Static detection has limits
The checker never runs the code. It sees imports written as plain strings, not modules picked at runtime, Node.js globals such as Buffer or __dirname used without an import, or which branch of a package your app reaches. It reads only the packages you list, so a dependency of a dependency that needs Node.js stays invisible unless you add it by name. It also stops after a fixed number of files per package and says so.
Frameworks and build tools such as Nuxt, Vite and Wrangler run at build time, so the checker skips them along with type packages. A framework that targets Workers is judged by what its build puts in the bundle, not by its package entry. A Nuxt module, such as @nuxt/ui, is the same case: its entry runs in the Nuxt build and imports Node.js freely, while the runtime code it adds is bundled by Nitro, so it reads as could not tell rather than as a false alarm.
03Rates
The numbers it uses
| Item | Date | Source |
|---|---|---|
| nodejs_compat on by default | 2026-08-04 | developers.cloudflare.com |
| nodejs_compat includes Wrangler's polyfills | 2024-09-23 | developers.cloudflare.com |
| node:http and node:https clients | 2025-08-15 | developers.cloudflare.com |
| A Worker uploaded through the API without a date | 2021-11-02 | developers.cloudflare.com |
| Item | On Workers | Source |
|---|---|---|
| node:assert | Supported | developers.cloudflare.com |
| node:async_hooks Only AsyncLocalStorage and AsyncResource; the rest of async_hooks is missing. | Partly supported | developers.cloudflare.com |
| node:buffer | Supported | developers.cloudflare.com |
| node:child_process Earlier: enable_nodejs_child_process_module | Stub only, from 2026-03-17 | developers.cloudflare.com |
| node:cluster Earlier: enable_nodejs_cluster_module | Stub only, from 2025-12-04 | developers.cloudflare.com |
| node:console Earlier: enable_nodejs_console_module | Partly supported, from 2025-09-21 | developers.cloudflare.com |
| node:constants | Polyfilled by Wrangler | github.com |
| node:crypto All of it except argon2, DSA and DH key pairs, and the ed448 and x448 curves. | Supported | developers.cloudflare.com |
| node:dgram Earlier: enable_nodejs_dgram_module | Stub only, from 2026-01-29 | developers.cloudflare.com |
| node:diagnostics_channel | Supported | developers.cloudflare.com |
| node:dns lookup, lookupService and resolve throw; the rest resolves over DNS over HTTPS. | Partly supported | developers.cloudflare.com |
| node:domain Earlier: enable_nodejs_domain_module | Stub only, from 2025-12-04 | developers.cloudflare.com |
| node:events | Supported | developers.cloudflare.com |
| node:fs A virtual file system: your bundle's modules, read-only, and a /tmp that lasts one request. Earlier: enable_nodejs_fs_module | Supported, from 2025-09-15 | developers.cloudflare.com |
| node:http Client APIs from 2025-08-15, http.createServer from 2025-09-01. Earlier: enable_nodejs_http_modules, enable_nodejs_http_server_modules | Supported, from 2025-09-01 | developers.cloudflare.com |
| node:http2 Earlier: enable_nodejs_http2_module | Stub only, from 2025-09-01 | developers.cloudflare.com |
| node:https Client APIs from 2025-08-15, http.createServer from 2025-09-01. Earlier: enable_nodejs_http_modules, enable_nodejs_http_server_modules | Supported, from 2025-09-01 | developers.cloudflare.com |
| node:inspector Earlier: enable_nodejs_inspector_module | Stub only, from 2026-01-29 | developers.cloudflare.com |
| node:module | Partly supported | developers.cloudflare.com |
| node:net Sockets connect out; net.Server is not supported. | Supported | developers.cloudflare.com |
| node:os Earlier: enable_nodejs_os_module | Partly supported, from 2025-09-15 | developers.cloudflare.com |
| node:path | Supported | developers.cloudflare.com |
| node:perf_hooks Earlier: enable_nodejs_perf_hooks_module | Partly supported, from 2026-03-17 | developers.cloudflare.com |
| node:process The full process object from 2025-09-15; before it, only nextTick, env, exit, getBuiltinModule, platform and features. Earlier: enable_nodejs_process_v2 | Supported, from 2025-09-15 | developers.cloudflare.com |
| node:punycode Earlier: enable_nodejs_punycode_module | Supported, from 2025-12-04 | developers.cloudflare.com |
| node:querystring | Supported | developers.cloudflare.com |
| node:readline Earlier: enable_nodejs_readline_module | Stub only, from 2026-03-17 | developers.cloudflare.com |
| node:repl Earlier: enable_nodejs_repl_module | Stub only, from 2026-03-17 | developers.cloudflare.com |
| node:sqlite Earlier: enable_nodejs_sqlite_module | Stub only, from 2026-01-29 | developers.cloudflare.com |
| node:stream | Supported | developers.cloudflare.com |
| node:string_decoder | Supported | developers.cloudflare.com |
| node:sys | Polyfilled by Wrangler | github.com |
| node:test | Partly supported | developers.cloudflare.com |
| node:timers | Supported | developers.cloudflare.com |
| node:tls Only connect, TLSSocket, checkServerIdentity and createSecureContext; servers are not supported. | Partly supported | developers.cloudflare.com |
| node:trace_events Earlier: enable_nodejs_trace_events_module | Stub only, from 2025-12-04 | developers.cloudflare.com |
| node:tty Earlier: enable_nodejs_tty_module | Stub only, from 2026-03-17 | developers.cloudflare.com |
| node:url | Supported | developers.cloudflare.com |
| node:util | Supported | developers.cloudflare.com |
| node:v8 Earlier: enable_nodejs_v8_module | Stub only, from 2026-03-17 | developers.cloudflare.com |
| node:vm Earlier: enable_nodejs_vm_module | Stub only, from 2025-10-01 | developers.cloudflare.com |
| node:wasi Earlier: enable_nodejs_wasi_module | Stub only, from 2025-12-04 | developers.cloudflare.com |
| node:worker_threads Earlier: enable_nodejs_worker_threads_module | Stub only, from 2026-03-17 | developers.cloudflare.com |
| node:zlib Earlier: nodejs_zlib | Supported, from 2024-09-23 | developers.cloudflare.com |
| node:_stream_wrap Earlier: enable_nodejs_stream_wrap_module | Stub only, from 2026-01-29 | developers.cloudflare.com |
04Questions
Questions
- Do I still need the nodejs_compat flag?
- Only on a compatibility date before the one the checker names. From that date, Workers turn on nodejs_compat and nodejs_compat_v2 by default and ignore the flags, so you can leave them in or take them out. On an earlier date, add nodejs_compat to compatibility_flags in wrangler.jsonc.
- Which compatibility date should I use?
- Today's, for a new project. Cloudflare recommends it and supports old dates forever, so you never have to move it. When you do move it, read the compatibility flags page for what changed in between, because some of those changes are backwards-incompatible on purpose.
- Which Node.js modules work on Cloudflare Workers?
- Most of what a server library reaches for, including buffer, crypto, events, fs, http, net, path, process, stream, url, util and zlib, some of them only from a given compatibility date. dns, os, tls and a few others work in part. child_process, worker_threads, vm and some others exist only as stubs that load but do not work. The table on this page lists every module.
- Why will a package with native code not run on Workers?
- Workers run your code in V8 isolates, not in a Node.js process, so a compiled .node addon has nothing to load into. sharp, bcrypt and better-sqlite3 are the usual cases, and each has a Workers route instead, such as the Images binding, password hashing through Web Crypto, and D1.
- Does a package that imports child_process break my Worker?
- Not by loading. With Node.js compatibility on, child_process is a stub, so the import succeeds and only calls into it fail. A library that spawns processes only in its command-line tool can work fine, while a package built to run commands, such as execa, cannot.
- How accurate is the check?
- It is static and heuristic. It resolves each package the way Wrangler does and reads its entry files, but it does not run them, follow the packages they depend on, see Node.js globals such as Buffer used without an import, or know which code paths your app calls. Treat a clean result as a good sign and confirm it with wrangler dev.
05Sources
Sources
Every fact on this page was read from these pages on .
- Cloudflare docs, Node.js compatibilitydevelopers.cloudflare.com/
workers/ runtime-apis/ nodejs/ - Cloudflare docs, Compatibility flagsdevelopers.cloudflare.com/
workers/ configuration/ compatibility-flags/ - Cloudflare docs, Compatibility datesdevelopers.cloudflare.com/
workers/ configuration/ compatibility-dates/ - Cloudflare docs, Wrangler bundlingdevelopers.cloudflare.com/
workers/ wrangler/ bundling/ - Wrangler source, build conditionsgithub.com/
cloudflare/ workers-sdk/ blob/ main/ packages/ wrangler/ src/ deployment-bundle/ bundle.ts - esbuild docs, conditions and main fieldsesbuild.github.io/
api/ #conditions - Node.js docs, conditional exportsnodejs.org/
api/ packages.html#conditional-exports - Cloudflare docs, How Workers worksdevelopers.cloudflare.com/
workers/ reference/ how-workers-works/ - Cloudflare docs, node:fsdevelopers.cloudflare.com/
workers/ runtime-apis/ nodejs/ fs/ - Cloudflare docs, node:cryptodevelopers.cloudflare.com/
workers/ runtime-apis/ nodejs/ crypto/ - Cloudflare docs, node:dnsdevelopers.cloudflare.com/
workers/ runtime-apis/ nodejs/ dns/ - Cloudflare docs, node:netdevelopers.cloudflare.com/
workers/ runtime-apis/ nodejs/ net/ - Cloudflare docs, node:tlsdevelopers.cloudflare.com/
workers/ runtime-apis/ nodejs/ tls/ - Cloudflare docs, AsyncLocalStoragedevelopers.cloudflare.com/
workers/ runtime-apis/ nodejs/ asynclocalstorage/ - unenv, the Node.js polyfills Wrangler usesgithub.com/
unjs/ unenv/ tree/ main/ src/ runtime/ node - Cloudflare docs, Images bindingdevelopers.cloudflare.com/
images/ optimization/ binding/ - Cloudflare docs, D1developers.cloudflare.com/
d1/ - Cloudflare docs, Web Cryptodevelopers.cloudflare.com/
workers/ runtime-apis/ web-crypto/ - Cloudflare docs, Browser Run with Puppeteerdevelopers.cloudflare.com/
browser-run/ puppeteer/ - Cloudflare docs, Browser Run with Playwrightdevelopers.cloudflare.com/
browser-run/ playwright/ - Cloudflare docs, Cron Triggersdevelopers.cloudflare.com/
workers/ configuration/ cron-triggers/ - Cloudflare docs, Queuesdevelopers.cloudflare.com/
queues/ - Cloudflare docs, WebSocketsdevelopers.cloudflare.com/
workers/ runtime-apis/ websockets/ - Cloudflare docs, Fetchdevelopers.cloudflare.com/
workers/ runtime-apis/ fetch/
Found something out of date? Tell us.
Nuxter
Building a SaaS on Nuxt?
Nuxter is a Nuxt 4 starter kit built for Cloudflare Workers, with Postgres through Hyperdrive, sessions, payments, email and queued jobs already running on the runtime.