cloudflare / cloudflare/workerd
Node.js Compat API Update Survey
- Dominant language
- C++
- Stars
- 8.7k
- Forks
- 739
- Avg merge
- 2d 20h
- Merged PRs (30d)
- 174
Description
# Node.js Compat Gaps: workerd vs Node.js v22–v26
New APIs added to Node.js between v22.0.0 (April 2024) and v26.0.0 (May 2026)
that are missing or incomplete in workerd's `node:` module implementations.
(List needs to be reviewed to determine if the AI agent missed items or got items wrong)
## `node:crypto`
- ~~`crypto.hash()` — one-shot hash without creating a Hash stream (v22)~~ Implemented
- `KeyObject.prototype.toCryptoKey()` — convert Node.js KeyObject to WebCrypto CryptoKey (v23)
- `x509.validFromDate` / `x509.validToDate` — Date object accessors on X509Certificate (v23)
- `crypto.randomUUIDv7()` — time-sortable UUID v7 generation (v26)
- `crypto.argon2()` / `crypto.argon2Sync()` — Argon2 password hashing (v26)
- ML-KEM / ML-DSA post-quantum key encapsulation: `encapsulate()`, `decapsulate()` (v26)
- `x509.signatureAlgorithm` / `x509.signatureAlgorithmOid` (v26)
- Ed25519 context parameter support (v26)
- ~~`crypto.generateKey()` — noted as not yet implemented in workerd TS layer~~ Implemented?
- `crypto.diffieHellman()` async variant (v26)
## `node:webcrypto`
- KEM operations: `encapsulateBits()`, `encapsulateKey()`, `decapsulateBits()`, `decapsulateKey()` (v26)
- `SubtleCrypto.supports()` (v26)
- `subtle.getPublicKey()` (v26)
- Argon2 derivation params (v26)
- cSHAKE, KMAC, KangarooTwelve, TurboShake algorithms (v26)
## ~~`node:async_hooks`~~
- ~~`AsyncLocalStorage` constructor options: `{ defaultValue, name }` (v24)~~ Implemented in workerd already
- ~~`AsyncLocalStorage.enterWith()` — throws "not implemented" in workerd~~ Intentionally omitted
- ~~`AsyncLocalStorage.disable()` — throws "not implemented" in workerd~~ Intentionally omitted
## `node:assert`
- ~~`assert.partialDeepStrictEqual()` (v24)~~ Implemented
- `Class: Assert` — custom assert instances (v26)
## `node:path`
- `path.matchesGlob()` / `path.posix.matchesGlob()` / `path.win32.matchesGlob()` — code exists but throws "not implemented" (v23)
## `node:util`
- `util.parseArgs()` — throws "not implemented" in workerd (v22)
- ~~`util.styleText()` — terminal text styling, accepts array of formats (v22)~~
- ~~`util.types.isFloat16Array()` (v24)~~
- ~~`util.parseEnv()` — parse .env file format (v24)~~
- ~~`util.aborted()` — promise that resolves on AbortSignal abort (v22)~~
- `util.diff()` — diffing utility (v25)
- `util.transferableAbortController()` — throws "not implemented" in workerd
- `util.transferableAbortSignal()` — throws "not implemented" in workerd
- `util.getSystemErrorMap()` — throws "not implemented" in workerd
- `util.getSystemErrorName()` — throws "not implemented" in workerd
- `util.getSystemErrorMessage()` — throws "not implemented" in workerd
- ~~`util.isDeepStrictEqual()` options parameter (v25)~~
## `node:buffer`
- ~~`buffer.isAscii()` (v22)~~
- ~~`buffer.isUtf8()` (v22)~~
- `Buffer.copyBytesFrom()` (v22)
- `buffer.resolveObjectURL()` — noted as not implemented in workerd
- ~~`blob.bytes()` (v22)~~
- `blob.textStream()` (v25)
- Aligned allocations: `Buffer.allocUnsafe(size, alignment)` (v25)
## `node:zlib`
- ZIP archive API: `ZipBuffer`, `ZipEntry`, `ZipFile`, `createZipArchive()` (v25)
- Iterable compression helpers (v25)
## `node:fs`
- `fs.openAsBlob()` — noted as TODO in workerd (v22)
- `fsPromises.mkdtempDisposable()` (v25)
- `Class: Utf8Stream` (v25)
- `Class: StatFs` (v24)
## `node:sqlite`
- `DatabaseSync` full implementation — constructor is deleted in workerd, only constants exported (v22, stability 1.2)
- `StatementSync` full implementation — constructor is deleted in workerd (v22)
- `Session` (changeset support) (v24)
- `SQLTagStore` (tagged template SQL) (v25)
- `database.aggregate()` (v25)
- `database.setAuthorizer()` (v25)
- `database.serialize()` / `database.deserialize()` (v25)
- `sqlite.backup()` — throws in workerd (v25)
- `Symbol.dispose` support on DatabaseSync/StatementSync (v24)
## `node:diagnostics_channel`
- `TracingChannel` class — noted as TODO in workerd (v24)
- `BoundedChannel` / `BoundedChannelScope` (v25)
- `RunStoresScope` class (v25)
- Built-in channels for HTTP/net/DNS auto-instrumentation (v24)
## `node:dns`
- `dns.resolveTlsa()` — DANE/TLSA record resolution (v25)
- `Resolver.cancel()` — noted as not implemented in workerd
## `node:events`
- `events.addAbortListener()` (v22)
- `EventEmitterAsyncResource` (v22)
## `node:stream`
- `stream.isDestroyed()` / `stream.isErrored()` / `stream.isReadable()` / `stream.isWritable()` — static utility functions (v22)
- ~~`Readable.fromWeb()` / `Readable.toWeb()` (v22)~~
- ~~`Writable.fromWeb()` / `Writable.toWeb()` (v22)~~
- ~~`Duplex.fromWeb()` / `Duplex.toWeb()` (v22)~~
## `node:http`
- ~~`Class: WebSocket` — built-in WebSocket in http module (v22)~~
- `response.writeEarlyHints()` (v22)
- `response.writeInformation()` (v25)
- `message.signal` — AbortSignal on IncomingMessage (v24)
- `server[Symbol.asyncDispose]()` (v24)
- `closeAllConnections()` / `closeIdleConnections()` (v22)
## `node:https`
- `server[Symbol.asyncDispose]()` (v24)
- `closeAllConnections()` / `closeIdleConnections()` (v22)
## `node:net`
- `net/promises` API: `netPromises.connect()`, `netPromises.listen()` (v25)
- `Class: BoundSocket` (v25)
- `SocketAddress.parse()` (v24)
- `server[Symbol.asyncDispose]()` (v24)
- `server[Symbol.asyncIterator]()` (v25)
- `net.BlockList` improvements (release pending)
## `node:tls`
- `tls.setDefaultCACertificates()` (v25)
- `tls.getCACertificates()` (v25)
- `tls.getCertificateCompressionAlgorithms()` (v26)
- `tlsSocket.setKeyCert()` — throws "not implemented" in workerd
- `tlsSocket.exportKeyingMaterial()` — throws "not implemented" in workerd
- `tlsSocket.getPeerCertificate()` — throws "not implemented" in workerd
- `tlsSocket.getCertificate()` — throws "not implemented" in workerd
- `tlsSocket.getPeerX509Certificate()` — throws "not implemented" in workerd
- `tlsSocket.getX509Certificate()` — throws "not implemented" in workerd
## `node:dgram`
- `socket.bindSync()` / `socket.connectSync()` (v25)
- `socket[Symbol.asyncDispose]()` (v24)
- (entire module is a non-functional stub in workerd)
## `node:http2`
- `http2.performServerHandshake()` (v24)
- Extended CONNECT protocol support (v24)
- (entire module is a non-functional stub in workerd)
## `node:vm`
- `SourceTextModule` class — not implemented in workerd
- `SyntheticModule` class — not implemented in workerd
- `vm.constants.DONT_CONTEXTIFY` (v25)
## `node:module`
- `module.findPackageJSON()` (v25)
- `module.stripTypeScriptTypes()` (v25)
- `module.registerHooks()` — synchronous loader hooks (v25)
- `module.register()` — async loader hooks (v22, deprecated v26)
- `module.enableCompileCache()` / `module.flushCompileCache()` / `module.getCompileCacheDir()` (v23)
- `module.syncBuiltinESMExports()` — noted as "might support in the future" in workerd
- Source map support (`module.SourceMap`, `module.findSourceMap`) — noted in workerd as future
## `node:process`
- `process.loadEnvFile()` (v22)
- `process.finalization.register()` / `process.finalization.registerBeforeExit()` (v22)
- `process.permission.has()` / `process.permission.drop()` (v24)
- `process.availableMemory()` (v22)
- `process.constrainedMemory()` (v22)
- `process.execve()` (v25)
- `process.ref()` / `process.unref()` (v25)
- `process.threadCpuUsage()` (v25)
- `process.features.require_module` (v23)
- `process.features.typescript` (v25)
## `node:os`
- `os.availableParallelism()` (v22)
- `os.machine()` (v22)
- (module exists in workerd but all functions return hardcoded stub values)
## `node:perf_hooks`
- `PerformanceResourceTiming` (v22)
- `RecordableHistogram` (v22)
- `eventLoopUtilization()` — returns stub zeros in workerd
- `createHistogram()` — throws in workerd
- `monitorEventLoopDelay()` — throws in workerd
- Built-in Net/DNS/HTTP performance detail types (v24)
- `Histogram` API improvements (pending release)
## `node:console`
- globalThis.console is not Node.js-compatible (noted as TODO in workerd)
## `node:v8`
- `v8.queryObjects()` (v22)
- CPU profiling API (v25)
- `Serializer` / `Deserializer` — noted as "implement later" in workerd
- `writeHeapSnapshot()` — noted as "implement later" in workerd
- `setHeapSnapshotNearHeapLimit()` — noted as "implement later" in workerd
- (most functions are no-ops or throw in workerd)
## `node:test`
- `describe()` / `it()` / `test()` runner — not implemented in workerd (only MockTracker ported)
- `mock.module()` (v22)
- `mock.getter()` / `mock.setter()` / `mock.property()` (v24)
- `MockTimers` (v22)
- Snapshot testing (v22)
- `context.plan()` (v24)
- `context.waitFor()` (v25)
- `context.log()` (v25)
- `assert.register()` (v25)
- `getTestContext()` (v25)
- Test tags (v25)
- Global setup/teardown (v24)
- Coverage reporters (v24)
- OpenTelemetry integration (v25)
## `node:timers`
- `Symbol.dispose` support on `Timeout` / `Immediate` (v24)
- `timersPromises.scheduler.yield()` (v24)
## `node:wasi`
- Full WASI implementation — constructor throws in workerd (noted as "we might want to implement")
## `node:worker_threads`
- `BroadcastChannel` — constructor throws in workerd (noted as TODO: use globalThis.BroadcastChannel)
## Global Web Platform APIs (exposed by Node.js)
- ~~`EventSource` — Server-Sent Events client (v25)~~
- `navigator.locks` — Web Locks API (v25)
- `CloseEvent` global (v23)
- `ErrorEvent` global (v25)
## `Symbol.dispose` / `Symbol.asyncDispose` Support
Node.js v24+ added explicit resource management protocol support to these built-in objects.
workerd implementations of these objects do not currently support it:
- `net.Server`
- `http.Server`
- `https.Server`
- `Timeout`
- `Immediate`
- `dgram.Socket`
- `DatabaseSync`
- `StatementSync`
- `fsPromises.mkdtemp` (returns disposable)
## Deprecations Not Yet Reflected
Node.js deprecated or removed these APIs; workerd still exposes them without warnings:
- `crypto.createCipher()` / `crypto.createDecipher()` — EOL in v26
- `url.parse()` — runtime deprecated in v24
- `SlowBuffer` — EOL in v25
- `_stream_duplex`, `_stream_passthrough`, `_stream_readable`, `_stream_transform`, `_stream_writable` — removed in v26
- `_tls_common` / `_tls_wrap` — deprecated in v25
- `util.isArray()`, `util.isBoolean()`, `util.isNull()`, `util.isNumber()`, `util.isString()`, `util.isObject()`, `util.isFunction()`, `util.isError()`, `util.isDate()`, `util.isRegExp()`, `util.isUndefined()`, `util.isSymbol()`, `util.isPrimitive()`, `util.isNullOrUndefined()`, `util.isBuffer()`, `util.log()`, `util._extend()` — EOL in v23
- `zlib.bytesRead` — removed in v23
- `fs.F_OK` / `fs.R_OK` / `fs.W_OK` / `fs.X_OK` — removed in v25 (use `fs.constants.*`)
- `dirent.path` — removed in v24 (use `dirent.parentPath`)
- `assert.CallTracker` — EOL in v25
- `crypto.fips` — runtime deprecated in v23
- `punycode` module — deprecated since v7
Contributor guide
Research direction
Start by reviewing the listed Node.js v22–v26 APIs against the corresponding workerd node: module implementations and the entries marked implemented, TODO, or not implemented. Verify which gaps and version claims are accurate, then update the survey so each remaining item has a confirmed status and clear scope.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- node.js
- Domain
- api, backend
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100