[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"tools-page-cloudflare-workers-compatibility-checker":3},{"page":4,"related":364,"variants":389},{"path":5,"name":6,"title":7,"description":8,"checkedAt":9,"sources":10,"faq":83,"related":102,"nuxter":107,"body":110,"tool":362,"preset":363},"\u002Ftools\u002Fcloudflare-workers-compatibility-checker","Workers compatibility checker","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.","2026-10-06",[11,14,17,20,23,26,29,32,35,38,41,44,47,50,53,56,59,62,65,68,71,74,77,80],{"label":12,"url":13},"Cloudflare docs, Node.js compatibility","https:\u002F\u002Fdevelopers.cloudflare.com\u002Fworkers\u002Fruntime-apis\u002Fnodejs\u002F",{"label":15,"url":16},"Cloudflare docs, Compatibility flags","https:\u002F\u002Fdevelopers.cloudflare.com\u002Fworkers\u002Fconfiguration\u002Fcompatibility-flags\u002F",{"label":18,"url":19},"Cloudflare docs, Compatibility dates","https:\u002F\u002Fdevelopers.cloudflare.com\u002Fworkers\u002Fconfiguration\u002Fcompatibility-dates\u002F",{"label":21,"url":22},"Cloudflare docs, Wrangler bundling","https:\u002F\u002Fdevelopers.cloudflare.com\u002Fworkers\u002Fwrangler\u002Fbundling\u002F",{"label":24,"url":25},"Wrangler source, build conditions","https:\u002F\u002Fgithub.com\u002Fcloudflare\u002Fworkers-sdk\u002Fblob\u002Fmain\u002Fpackages\u002Fwrangler\u002Fsrc\u002Fdeployment-bundle\u002Fbundle.ts",{"label":27,"url":28},"esbuild docs, conditions and main fields","https:\u002F\u002Fesbuild.github.io\u002Fapi\u002F#conditions",{"label":30,"url":31},"Node.js docs, conditional exports","https:\u002F\u002Fnodejs.org\u002Fapi\u002Fpackages.html#conditional-exports",{"label":33,"url":34},"Cloudflare docs, How Workers works","https:\u002F\u002Fdevelopers.cloudflare.com\u002Fworkers\u002Freference\u002Fhow-workers-works\u002F",{"label":36,"url":37},"Cloudflare docs, node:fs","https:\u002F\u002Fdevelopers.cloudflare.com\u002Fworkers\u002Fruntime-apis\u002Fnodejs\u002Ffs\u002F",{"label":39,"url":40},"Cloudflare docs, node:crypto","https:\u002F\u002Fdevelopers.cloudflare.com\u002Fworkers\u002Fruntime-apis\u002Fnodejs\u002Fcrypto\u002F",{"label":42,"url":43},"Cloudflare docs, node:dns","https:\u002F\u002Fdevelopers.cloudflare.com\u002Fworkers\u002Fruntime-apis\u002Fnodejs\u002Fdns\u002F",{"label":45,"url":46},"Cloudflare docs, node:net","https:\u002F\u002Fdevelopers.cloudflare.com\u002Fworkers\u002Fruntime-apis\u002Fnodejs\u002Fnet\u002F",{"label":48,"url":49},"Cloudflare docs, node:tls","https:\u002F\u002Fdevelopers.cloudflare.com\u002Fworkers\u002Fruntime-apis\u002Fnodejs\u002Ftls\u002F",{"label":51,"url":52},"Cloudflare docs, AsyncLocalStorage","https:\u002F\u002Fdevelopers.cloudflare.com\u002Fworkers\u002Fruntime-apis\u002Fnodejs\u002Fasynclocalstorage\u002F",{"label":54,"url":55},"unenv, the Node.js polyfills Wrangler uses","https:\u002F\u002Fgithub.com\u002Funjs\u002Funenv\u002Ftree\u002Fmain\u002Fsrc\u002Fruntime\u002Fnode",{"label":57,"url":58},"Cloudflare docs, Images binding","https:\u002F\u002Fdevelopers.cloudflare.com\u002Fimages\u002Foptimization\u002Fbinding\u002F",{"label":60,"url":61},"Cloudflare docs, D1","https:\u002F\u002Fdevelopers.cloudflare.com\u002Fd1\u002F",{"label":63,"url":64},"Cloudflare docs, Web Crypto","https:\u002F\u002Fdevelopers.cloudflare.com\u002Fworkers\u002Fruntime-apis\u002Fweb-crypto\u002F",{"label":66,"url":67},"Cloudflare docs, Browser Run with Puppeteer","https:\u002F\u002Fdevelopers.cloudflare.com\u002Fbrowser-run\u002Fpuppeteer\u002F",{"label":69,"url":70},"Cloudflare docs, Browser Run with Playwright","https:\u002F\u002Fdevelopers.cloudflare.com\u002Fbrowser-run\u002Fplaywright\u002F",{"label":72,"url":73},"Cloudflare docs, Cron Triggers","https:\u002F\u002Fdevelopers.cloudflare.com\u002Fworkers\u002Fconfiguration\u002Fcron-triggers\u002F",{"label":75,"url":76},"Cloudflare docs, Queues","https:\u002F\u002Fdevelopers.cloudflare.com\u002Fqueues\u002F",{"label":78,"url":79},"Cloudflare docs, WebSockets","https:\u002F\u002Fdevelopers.cloudflare.com\u002Fworkers\u002Fruntime-apis\u002Fwebsockets\u002F",{"label":81,"url":82},"Cloudflare docs, Fetch","https:\u002F\u002Fdevelopers.cloudflare.com\u002Fworkers\u002Fruntime-apis\u002Ffetch\u002F",[84,87,90,93,96,99],{"question":85,"answer":86},"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.",{"question":88,"answer":89},"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.",{"question":91,"answer":92},"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.",{"question":94,"answer":95},"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.",{"question":97,"answer":98},"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.",{"question":100,"answer":101},"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.",[103,104,105,106],"cloudflare-workers-pricing-calculator","nuxt-upgrade-checker","cloudflare-cron-generator","cloudflare-d1-pricing-calculator",{"body":108,"to":109},"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.","\u002Ffeatures",{"type":111,"value":112,"toc":356},"minimark",[113,118,122,164,190,217,221,233,239,249,255,268,272,282,285,320,331,335,345,352],[114,115,117],"h2",{"id":116},"how-the-checker-reads-a-package","How the checker reads a package",[119,120,121],"p",{},"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.",[119,123,124,125,129,130,133,134,137,138,141,142,133,145,148,149,151,152,129,154,133,157,160,161,163],{},"From the file list and the package's manifest it finds the file Wrangler would bundle. Wrangler builds with esbuild and sets the ",[126,127,128],"code",{},"workerd",", ",[126,131,132],{},"worker"," and ",[126,135,136],{},"browser"," conditions, so in a package's ",[126,139,140],{},"exports"," the checker takes the first key among those, ",[126,143,144],{},"import",[126,146,147],{},"default",", in the order the package lists them. A package without ",[126,150,140],{}," falls back to its ",[126,153,136],{},[126,155,156],{},"module",[126,158,159],{},"main"," fields, in that order, and a ",[126,162,136],{}," map that swaps a file or switches a module off is applied too.",[119,165,166,167,129,169,129,172,133,175,178,179,182,183,186,187,189],{},"It then reads that entry file and the files it imports inside the same package, up to a cap, and collects every ",[126,168,144],{},[126,170,171],{},"export … from",[126,173,174],{},"require()",[126,176,177],{},"import()"," with a fixed string. A ",[126,180,181],{},"require"," inside a ",[126,184,185],{},"try"," block or a dynamic ",[126,188,177],{}," counts as optional, because a package that guards a Node.js import usually has a fallback.",[119,191,192,193,196,197,200,201,204,205,208,209,212,213,216],{},"Before reading any code, it looks for signs of native code: a ",[126,194,195],{},".node"," file or ",[126,198,199],{},"binding.gyp"," in the package, an install script that runs node-gyp or prebuild-install, a dependency on a native loader such as ",[126,202,203],{},"node-gyp-build",", a set of per-platform binary packages in ",[126,206,207],{},"optionalDependencies",", or an ",[126,210,211],{},"os"," or ",[126,214,215],{},"cpu"," list that limits where it installs.",[114,218,220],{"id":219},"what-the-five-results-mean","What the five results mean",[119,222,223,227,228,212,230,232],{},[224,225,226],"strong",{},"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 ",[126,229,128],{},[126,231,132],{}," condition.",[119,234,235,238],{},[224,236,237],{},"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.",[119,240,241,244,245,248],{},[224,242,243],{},"Loads, some calls fail."," The package also imports a module that Workers ship only as a stub, such as ",[126,246,247],{},"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.",[119,250,251,254],{},[224,252,253],{},"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.",[119,256,257,260,261,212,264,267],{},[224,258,259],{},"Could not tell."," npm does not know the package or version, the version is local such as ",[126,262,263],{},"workspace:",[126,265,266],{},"file:",", the package has no entry file to import, its entry file is too large to read here, or it is a Nuxt module.",[114,269,271],{"id":270},"the-compatibility-date-and-nodejs_compat","The compatibility date and nodejs_compat",[119,273,274,277,278,281],{},[126,275,276],{},"compatibility_date"," pins the version of the Workers runtime your Worker runs on, and ",[126,279,280],{},"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.",[119,283,284],{},"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:",[286,287,292],"pre",{"className":288,"code":289,"language":290,"meta":291,"style":291},"language-jsonc shiki shiki-themes github-light github-light github-dark","{\n  \"compatibility_date\": \"2026-03-17\",\n  \"compatibility_flags\": [\"nodejs_compat\"],\n}\n","jsonc","",[126,293,294,302,308,314],{"__ignoreMap":291},[295,296,299],"span",{"class":297,"line":298},"line",1,[295,300,301],{},"{\n",[295,303,305],{"class":297,"line":304},2,[295,306,307],{},"  \"compatibility_date\": \"2026-03-17\",\n",[295,309,311],{"class":297,"line":310},3,[295,312,313],{},"  \"compatibility_flags\": [\"nodejs_compat\"],\n",[295,315,317],{"class":297,"line":316},4,[295,318,319],{},"}\n",[119,321,322,323,326,327,330],{},"If you keep an older date, type it in. The checker keeps it when it is new enough, adds ",[126,324,325],{},"nodejs_compat"," when the date needs it, and otherwise says which date to move to, or which ",[126,328,329],{},"enable_nodejs_…_module"," flags would keep your date working instead.",[114,332,334],{"id":333},"static-detection-has-limits","Static detection has limits",[119,336,337,338,212,341,344],{},"The checker never runs the code. It sees imports written as plain strings, not modules picked at runtime, Node.js globals such as ",[126,339,340],{},"Buffer",[126,342,343],{},"__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.",[119,346,347,348,351],{},"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 ",[126,349,350],{},"@nuxt\u002Fui",", 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.",[353,354,355],"style",{},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":291,"searchDepth":304,"depth":304,"links":357},[358,359,360,361],{"id":116,"depth":304,"text":117},{"id":219,"depth":304,"text":220},{"id":270,"depth":304,"text":271},{"id":333,"depth":304,"text":334},"cloudflare-workers-compatibility-checker",null,[365,371,377,383],{"path":366,"tool":103,"name":367,"title":368,"description":369,"summary":370,"checkedAt":9},"\u002Ftools\u002Fcloudflare-workers-pricing-calculator","Cloudflare Workers pricing calculator","Cloudflare Workers Pricing Calculator for a SaaS","Cloudflare Workers pricing calculator for a SaaS. Turn monthly users into a bill for Workers, D1, KV, R2, Queues and AI, and find the first Free limit you hit.","Turn monthly users into a Workers, D1, KV, R2, Queues and AI bill, and find the first Free plan limit you hit.",{"path":372,"tool":104,"name":373,"title":374,"description":375,"summary":376,"checkedAt":9},"\u002Ftools\u002Fnuxt-upgrade-checker","Nuxt upgrade checker","Nuxt 3 to 4 Migration Checker for Modules and Config","Plan a Nuxt 3 to 4 migration. Paste package.json to see which modules declare Nuxt 4 or 5, which nuxt.config options break, and the official checklist.","Paste a package.json to see which modules declare Nuxt 4 or 5, which config options break, and the official checklist.",{"path":378,"tool":105,"name":379,"title":380,"description":381,"summary":382,"checkedAt":9},"\u002Ftools\u002Fcloudflare-cron-generator","Cloudflare cron trigger generator","Cloudflare Cron Triggers Generator and Tester","Build and test Cloudflare Cron Triggers: plain-English meaning, the next runs in UTC and your time zone, and the Wrangler and Nitro scheduledTasks config.","Build a cron trigger, read it in plain English, see its next runs and copy the Wrangler and Nitro config.",{"path":384,"tool":106,"name":385,"title":386,"description":387,"summary":388,"checkedAt":9},"\u002Ftools\u002Fcloudflare-d1-pricing-calculator","Cloudflare D1 pricing calculator","Cloudflare D1 Pricing Calculator and Batch Limits","Cloudflare D1 pricing calculator. Turn users and queries into rows read and written, check the Free plan's daily limits, and size batch inserts under D1's caps.","Rows read and written, storage and the Free plan's daily limits, plus batch sizes that fit D1's caps.",[]]