new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

Cloudflare Workers · Runtime APIs · all subjects

runtime

283 notes in this subject, read out of this brain and free to use. This is page 2 of 5.

diagnostics_channel module overview

The diagnostics_channel module provides an API to create named channels to report arbitrary message data for diagnostics purposes. The API is a simple event pub/sub model designed to support low-overhead diagnostics reporting.

Creating and publishing to a diagnostics channel

To publish messages to a channel, acquire a channel object using channel('channel-name'), then call publish() with any JavaScript value. Example: const myChannel = channel('my-channel'); myChannel.publish({ foo: 'bar' });

TracingChannel with AsyncLocalStorage

TracingChannel can bind AsyncLocalStorage using channels.start.bindStore(asyncLocalStorageInstance) to maintain context across async operations. The example shows using tracingChannel('my-channel') and binding to AsyncLocalStorage to track request IDs across start, end, asyncStart, asyncEnd, and error handlers while tracing promise execution with channel.tracePromise().

TracingChannel purpose

TracingChannel is a collection of Channels which together express a single traceable action. It is used to formalize and simplify the process of producing events for tracing application flow.

Diagnostics channel messages in Tail Workers use structured clone

Messages published to Tail Workers are passed through the structured clone algorithm, so only values that can be successfully cloned are supported.

Diagnostics channel integration with Tail Workers

When using Tail Workers, all messages published to any channel are forwarded to the Tail Worker. Within the Tail Worker, diagnostic channel messages are accessed via the diagnosticsChannelEvents property on each event, which contains timestamp, channel, and message properties.

Subscribing to diagnostics channel messages

To receive messages on a channel, use subscribe('channel-name', callback) where the callback receives the message. Subscribers are invoked synchronously in the order they were registered, similar to EventTarget or Node.js EventEmitter.

TracingChannel handler methods

TracingChannel subscribers receive an object with handler methods: start, end, asyncStart, asyncEnd, and error.

node:dns module availability in Workers

The node:dns module is available in Cloudflare Workers for name resolution via DNS over HTTPS using Cloudflare DNS at 1.1.1.1.

DNS requests count toward subrequest limit

DNS requests made via node:dns execute as subrequests and count against the Worker's subrequest limit.

node:dns functions not implemented

The following node:dns functions are not available and throw 'Not implemented' errors when called: lookup, lookupService, and resolve.

node:dns example with resolve4

Example of using node:dns in Workers: ```ts import dns from 'node:dns'; let response = await dns.promises.resolve4('cloudflare.com', 'NS'); ``` This example demonstrates resolving IPv4 addresses with DNS over HTTPS.

VFS file path and storage limits

The Workers Virtual File System has the following limits: maximum total length of a file path is 4096 characters (including percent-encoding of special characters); maximum number of path segments is 48; maximum size of an individual file is 128 MB total.

VFS memory limits for temporary files

Since all temporary files are held in memory, the total size of all temporary files and directories created counts towards your Worker's memory limit. If you exceed this limit, the Worker instance will be terminated and restarted.

Writing temporary files example

Example of writing and reading temporary files in /tmp: ```js import { writeFileSync, readFileSync } from "node:fs"; export default { fetch(request) { writeFileSync("/tmp/hello.txt", "Hello, world!"); const contents = readFileSync("/tmp/hello.txt", "utf8"); return new Response(`File contents: ${contents}`); }, }; ```

Workers Virtual File System (VFS) structure

The Workers Virtual File System is a memory-based file system with three main directories: /bundle (contains read-only files for all modules in the Worker bundle), /tmp (writable directory for temporary files with per-request scope), and /dev (contains character devices: /dev/null, /dev/random, /dev/full, /dev/zero).

Reading files from Worker bundle example

Example of reading a config file from the Worker bundle: ```js import { readFileSync } from "node:fs"; const config = readFileSync("/bundle/config.txt", "utf8"); export default { async fetch(request) { return new Response(`Config contents: ${config}`); }, }; ```

Unsupported node:fs APIs in Workers

The following node:fs APIs are not supported or only partially supported in Workers: fs.watch and fs.watchFile (file change watching); fs.globSync() and other glob APIs (not implemented); the force option in fs.rm API (not implemented); file permissions and ownership (not supported).

node:fs module availability in Workers

The node:fs module is available in Workers runtimes that support Node.js compatibility using the nodejs_compat compatibility flag. Any Worker running with nodejs_compat enabled and with a compatibility date of 2025-09-01 or later will have access to node:fs by default. For earlier compatibility dates, you can enable node:fs using a combination of the nodejs_compat and enable_nodejs_fs_module flags. To disable node:fs, set the disable_nodejs_fs_module flag.

VFS timestamp limitations

Timestamps for files in the VFS are always set to the Unix epoch (1970-01-01T00:00:00Z). Operations that rely on timestamps, like fs.stat, will always return the same timestamp for all files in the VFS.

VFS file system synchronicity

All operations on the Workers Virtual File System are synchronous. You can use synchronous, asynchronous callback, or promise-based APIs provided by the node:fs module, but all operations will be performed synchronously.

/dev character devices in VFS

The /dev directory contains four character devices: /dev/null (discards all written data and returns EOF on read), /dev/random (provides random bytes on reads and is only accessible within request context), /dev/full (always returns EOF on reads), and /dev/zero (provides infinite stream of zero bytes).

/tmp directory behavior and limitations

The /tmp directory is writable and allows you to create temporary files, directories, and symlinks. However, the contents of /tmp are not persistent and are unique to each request. Files created in /tmp within one request will not be available in other concurrent or subsequent requests.

/bundle directory contents and usage

The /bundle directory contains files for all modules included in your Worker bundle as read-only files. Reading from the bundle is useful when you need to access a config file or a template that is included in your Worker bundle. Files in /bundle can be read using APIs like readFileSync or read().

httpServerHandler direct server example

import http from "node:http"; import { httpServerHandler } from "cloudflare:node"; const server = http.createServer((req, res) => { res.end("hello world"); }); // Pass server directly - automatically calls listen() if needed export default httpServerHandler(server);

IncomingMessage instanceof check example

import { get, IncomingMessage } from "node:http"; import { ok } from "node:assert"; export default { async fetch() { // ... get("http://example.org", (res) => { ok(res instanceof IncomingMessage); }); // ... }, };

http.ServerResponse streaming example

import { createServer, ServerResponse } from "node:http"; import { httpServerHandler } from "cloudflare:node"; import { ok } from "node:assert"; const server = createServer((req, res) => { ok(res instanceof ServerResponse); // Set multiple headers at once res.writeHead(200, { "Content-Type": "application/json", "X-Custom-Header": "Workers-HTTP", }); // Stream response data res.write('{"data": ['); res.write('{"id": 1, "name": "Item 1"},'); res.write('{"id": 2, "name": "Item 2"}'); res.write("]}"); // End the response res.end(); }); export default httpServerHandler(server);

http.Server class constructor example

import { Server } from "node:http"; import { httpServerHandler } from "cloudflare:node"; const server = new Server((req, res) => { res.writeHead(200, { "Content-Type": "application/json" }); res.end(JSON.stringify({ message: "Hello from HTTP Server!" })); }); server.listen(8080); export default httpServerHandler({ port: 8080 });

IncomingMessage cloudflare property example

import { createServer } from "node:http"; import { httpServerHandler } from "cloudflare:node"; const server = createServer((req, res) => { console.log(req.cloudflare.cf.country); console.log(req.cloudflare.cf.ray); res.write("Hello, World!"); res.end(); }); server.listen(8080); export default httpServerHandler({ port: 8080 });

handleAsNodeRequest example

import { createServer } from "node:http"; import { handleAsNodeRequest } from "cloudflare:node"; const server = createServer((req, res) => { res.writeHead(200, { "Content-Type": "text/plain" }); res.end("Hello from Node.js HTTP server!"); }); server.listen(8080); export default { fetch(request) { return handleAsNodeRequest(8080, request); }, };

httpServerHandler port-based routing example

import http from "node:http"; import { httpServerHandler } from "cloudflare:node"; const server = http.createServer((req, res) => { res.end("hello world"); }); server.listen(8080); export default httpServerHandler({ port: 8080 });

IncomingMessage socket property differences in Workers

In Workers, the socket attribute on IncomingMessage does not extend from net.Socket and only contains the following properties: encrypted, remoteFamily, remoteAddress, remotePort, localAddress, localPort, and destroy() method. The remoteAddress returns 127.0.0.1 when ran locally. The remotePort returns a random port number between 2^15 and 2^16. The localAddress returns the value of request's host header if it exists, otherwise 127.0.0.1. The localPort returns the port number assigned to the server instance. The req.socket.destroy() falls through to req.destroy().

node:http differences with fetch API wrapper

Because the Workers implementation of node:http is a wrapper around the global fetch API, there are behavioral differences and limitations: Connection headers are not used; Workers manages connections automatically. Content-Length headers are handled the same way as in the fetch API; if a body is provided, the header is set automatically and manually set values are ignored. Expect: 100-continue headers are not supported. Trailing headers are not supported. The 'continue', 'information', 'socket', and 'upgrade' events are not supported. Gaining direct access to the underlying socket is not supported.

http.ServerResponse unsupported features in Workers

The Workers implementation of http.ServerResponse does not support the following: assignSocket() and detachSocket() methods, trailer headers, writeContinue() and writeEarlyHints() methods, 1xx responses in general.

http.ServerResponse class

The http.ServerResponse class represents the server-side response object passed to request handlers. It provides methods for writing response headers and body data, and extends the Node.js Writable stream class. Methods include writeHead() to set response status and headers, write() to stream response data, and end() to finish the response.

handleAsNodeRequest function

The handleAsNodeRequest function from cloudflare:node provides direct control over request routing, directly routing a Worker request to a Node.js server running on a specific port. This approach gives full control over the fetch handler while still leveraging Node.js HTTP servers for request processing. Usage: return handleAsNodeRequest(8080, request);

httpServerHandler usage patterns

httpServerHandler can be used in two ways: export default httpServerHandler(server) to pass the server directly and automatically call listen() if needed, or server.listen(8080); export default httpServerHandler({ port: 8080 }) for port-based routing.

httpServerHandler function

The httpServerHandler function integrates Node.js HTTP servers with the Cloudflare Workers request model. It supports two API patterns: passing the server directly (simplified, automatically calls listen() if needed), or using port-based routing. The handler automatically routes incoming Worker requests to the Node.js server. When using port-based routing, the port number acts as a routing key to determine which server handles requests.

http.Server.listen port as routing key

When using httpServerHandler in Workers, the port number specified in server.listen() acts as a routing key to determine which HTTP server instance handles requests, rather than an actual network port. This allows multiple servers to coexist in the same Worker using different port numbers for identification.

http.Server differences in Workers

The Workers implementation of http.Server has the following differences from Node.js: connection management methods such as closeAllConnections() and closeIdleConnections() are not implemented. Only listen() variants with a port number or no parameters are supported: listen(), listen(0, callback), listen(callback), etc. The following server options are not supported: maxHeaderSize, insecureHTTPParser, keepAliveTimeout, connectionsCheckingInterval.

http.Server class

The http.Server class represents an HTTP server and provides methods for handling incoming requests. It extends the Node.js EventEmitter class and can be used to create custom server implementations. When using httpServerHandler, the port number specified in server.listen() acts as a routing key rather than an actual network port, allowing multiple servers to coexist within the same Worker by using different port numbers. Using a port value of 0, null, or undefined will result in a random port number being assigned.

http.createServer method

http.createServer creates an HTTP server instance that can handle incoming requests. The method accepts an optional request listener callback function that receives req and res parameters.

http.Agent implementation in Workers

A partial implementation of the Node.js http.Agent class is available in Workers. An Agent manages HTTP connection reuse by maintaining request queues per host/port. In the workers environment, such low-level management of network connections and ports is not relevant because it is handled by Cloudflare infrastructure. The Workers implementation is a stub that does not support connection pooling or keep-alive. The agent.protocol property returns 'http:'.

OutgoingMessage class

The OutgoingMessage class represents an HTTP response that is sent to the client. It provides methods for writing response headers and body, as well as for ending the response. OutgoingMessage extends from the Node.js stream.Writable stream class. Both ClientRequest and ServerResponse extend from and inherit from OutgoingMessage.

IncomingMessage differences in Workers

The Workers implementation of IncomingMessage has the following differences from Node.js: trailer headers are not supported. The socket attribute does not extend from net.Socket. Socket attributes remoteAddress, remotePort, localAddress, localPort, and destroy() method behave differently than Node.js counterparts.

http.Server lifecycle management

Failing to call close() on an HTTP server may result in the server persisting until the worker is destroyed. In most cases, this is not an issue since servers typically live for the lifetime of the worker. However, if you need to create multiple servers during a worker's lifetime or want explicit lifecycle control such as in test scenarios, call close() when you're done with the server, or use explicit resource management.

IncomingMessage class in Workers

The IncomingMessage class represents an HTTP request or response received from a client. It extends from the Readable stream class and provides methods for reading request headers and body. The Workers implementation includes a cloudflare property on IncomingMessage objects that contains cloudflare.cf properties with Cloudflare-specific request properties.

http.get method implementation

http.get performs a GET request to the specified URL and invokes the callback with the response. It is a convenience method that simplifies making HTTP GET requests without manually configuring request options. The get method is a wrapper around fetch() and may be used only within an exported fetch or similar handler. Outside of such a handler, attempts to use get will throw an error. The implementation is subject to the same limits as the global fetch API.

http.request method implementation

http.request creates an HTTP request with customizable options like method, headers, and body, providing full control over request configuration. It returns a Node.js stream.Writable for sending request data. The request method is a wrapper around fetch() and may be used only within an exported fetch or similar handler. Outside of such a handler, attempts to use request will throw an error.

http.createServer example

import { createServer } from "node:http"; import { httpServerHandler } from "cloudflare:node"; const server = createServer((req, res) => { res.writeHead(200, { "Content-Type": "text/plain" }); res.end("Hello from Node.js HTTP server!"); }); server.listen(8080); export default httpServerHandler({ port: 8080 });

enable_nodejs_http_server_modules compatibility flag

To use HTTP server-side methods such as http.createServer, http.Server, and http.ServerResponse, you must enable the enable_nodejs_http_server_modules compatibility flag in addition to the nodejs_compat flag. This flag is automatically enabled for Workers using a compatibility date of 2025-09-01 or later when nodejs_compat is enabled. For Workers using an earlier compatibility date, manually enable it by adding the flag to the Wrangler configuration file.

http.request example with options

import { get } from "node:http"; export default { async fetch() { const { promise, resolve, reject } = Promise.withResolvers(); get( { method: "GET", protocol: "http:", hostname: "example.org", path: "/", }, (res) => { let data = ""; res.setEncoding("utf8"); res.on("data", (chunk) => { data += chunk; }); res.on("end", () => { resolve(new Response(data)); }); res.on("error", reject); }, ) .on("error", reject) .end(); return promise; }, };

http.get and http.request require promise handling

When using http.get or http.request, it is necessary to arrange for requests to be correctly awaited in the fetch handler using a promise, or the fetch may be canceled prematurely when the handler returns.

Unsupported http.request and http.get options

The following options passed to the request and get methods are not supported: maxHeaderSize, insecureHTTPParser, createConnection, lookup, socketPath.

http.Agent protocol property example

import { Agent } from "node:http"; import { strictEqual } from "node:assert"; const agent = new Agent(); strictEqual(agent.protocol, "http:");

Non-functional stub modules

Some Node.js modules are available as non-functional stubs that can be imported or required but do not provide working implementations. These stubs allow packages that check for module presence to load in Workers, but are not suitable for direct application code use.

Node.js API polyfills via Wrangler

When nodejs_compat flag is enabled with compatibility date 2024-09-23 or later, Wrangler automatically injects polyfills using unenv for Node.js APIs not yet supported in the Workers runtime. These polyfilled methods either noop or throw an error with message "[unenv] <method name> is not implemented yet!"

Supported Node.js APIs in Workers

The following Node.js APIs are natively supported (🟢) or partially supported (🟡) in Workers Runtime: Assertion testing (supported), Asynchronous context tracking (supported), Buffer (supported), Console (partially supported), Crypto (supported), Debugger (supported via Chrome DevTools), Diagnostics Channel (supported), DNS (partially supported), Errors (supported), Events (supported), File system (supported), Globals (supported), HTTP (supported), HTTPS (supported), Module (partially supported), Net (supported), OS (partially supported), Path (supported), Performance hooks (partially supported), Process (supported), Punycode (supported), Query strings (supported), Stream (supported), String decoder (supported), Test runner (partially supported), Timers (supported), TLS/SSL (partially supported), URL (supported), Utilities (supported), Web Crypto API (supported), Web Streams API (supported), Zlib (supported).

Node.js compatibility flag configuration

In wrangler.jsonc, set `"compatibility_flags": ["nodejs_compat"]` and `"compatibility_date": "2024-09-23"` or later to enable Node.js API support.

Enable Node.js APIs with nodejs_compat flag

To enable built-in Node.js APIs and add polyfills in Workers, add the `nodejs_compat` compatibility flag to your Wrangler configuration file and ensure your Worker's compatibility date is 2024-09-23 or later.

Give your agent this brain