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

bindings

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

Vectorize binding overview

Vectorize is Cloudflare's globally distributed vector database. It is available as a runtime binding in Cloudflare Workers and provides APIs to interact with Vectorize from worker code.

Vectorize reference documentation location

The complete Vectorize client API reference is available at /vectorize/reference/client-api/.

Version metadata binding configuration

To use the version metadata binding, add a `version_metadata` object to your Worker's Wrangler configuration file with a `binding` property set to the name you want to use (for example, `CF_VERSION_METADATA`).

Version metadata binding interface properties

The version metadata binding exposes three properties: `id` (the Worker version ID), `tag` (the version tag), and `timestamp` (the timestamp of when the version was created). These are accessed via the binding name specified in the Wrangler configuration.

Version metadata binding use cases

Worker version metadata can be used in events sent to Workers Analytics Engine or to any third-party analytics/metrics service to aggregate by Worker version.

Version metadata binding example with Analytics Engine

The following code shows how to access version metadata and send it to Workers Analytics Engine: ```js export default { async fetch(request, env, ctx) { const { id: versionId, tag: versionTag, timestamp: versionTimestamp } = env.CF_VERSION_METADATA; env.WAE.writeDataPoint({ indexes: [versionId], blobs: [versionTag, versionTimestamp], //... }); //... }, }; ```

Version metadata binding TypeScript interface example

The following TypeScript code shows how to type the environment with version metadata binding: ```ts interface Environment { CF_VERSION_METADATA: WorkerVersionMetadata; WAE: AnalyticsEngineDataset; } export default { async fetch(request, env, ctx) { const { id: versionId, tag: versionTag } = env.CF_VERSION_METADATA; env.WAE.writeDataPoint({ indexes: [versionId], blobs: [versionTag], //... }); //... }, } satisfies ExportedHandler<Env>; ```

mTLS binding configuration in wrangler.json

Add an mTLS certificate binding to your Worker project's Wrangler file under the mtls_certificates array. Each binding requires a binding name and certificate_id. Example: {"binding": "MY_CERT", "certificate_id": "<CERTIFICATE_ID>"}

Upload mTLS certificate with wrangler command

Upload a certificate and private key using: npx wrangler mtls-certificate upload --cert cert.pem --key key.pem --name my-client-cert. This command requires the SSL and Certificates Edit API token scope.

mTLS certificate ID retrieval

Certificate IDs are displayed after uploading a certificate. Certificate IDs can also be viewed later with the command wrangler mtls-certificate list.

mTLS binding fetch method API

An mTLS certificate binding variable in the Worker environment has a fetch() method available with the exact same signature as the global fetch API. This fetch() method automatically presents the client certificate when establishing the TLS connection.

mTLS binding JavaScript usage example

export default { async fetch(request, environment) { return await environment.MY_CERT.fetch("https://a-secured-origin.com"); }, };

mTLS binding TypeScript usage example

interface Env { MY_CERT: Fetcher; } export default { async fetch(request, environment): Promise<Response> { return await environment.MY_CERT.fetch("https://a-secured-origin.com") } } satisfies ExportedHandler<Env>;

mTLS binding type interface

An mTLS certificate binding is of type Fetcher in TypeScript. It provides the same interface as service bindings.

mTLS limitation with Cloudflare proxied zones

mTLS for Workers cannot be used for requests made to a service that is a proxied zone on Cloudflare. If a Worker presents a client certificate to a service proxied by Cloudflare, Cloudflare will return a 520 error.

mTLS API token scope requirement

The wrangler mtls-certificate upload command requires the SSL and Certificates Edit API token scope. When using OAuth flow triggered by wrangler login, the correct scope is set automatically. When using API tokens, the correct scope must be manually set.

Workflows binding overview

Workflows is a Cloudflare Workers runtime binding that allows you to build durable, multi-step applications using Workers. The Workflows API is available through the workers runtime.

Workflows documentation location

The complete Workflows API documentation is located at /workflows/ in the Cloudflare documentation.

WorkerCode structure: mainModule

WorkerCode.mainModule is a required string field specifying the name of the Worker's main module. This must be one of the modules listed in the modules field.

Worker Loader binding allows dynamic isolate creation

A Worker Loader binding allows you to load additional Workers containing arbitrary code at runtime. It enables dynamically spawning isolates that run arbitrary code.

Isolates are lightweight containers cheaper than VMs

Isolates are lightweight containers used by the Workers platform instead of containers or VMs. They can be started in milliseconds and it is fine to start one just to run a snippet of code and immediately discard it.

Worker Loader sandboxing blocks or redirects network

Worker Loaders enable sandboxing of code. You can intercept or block all network requests made by the Worker within, and supply the sandboxed Worker with custom bindings to represent specific resources it should be allowed to access.

Worker Loader get() method signature

The Worker Loader has a single method get(id: string, getCodeCallback: () => Promise<WorkerCode>): WorkerStub. It loads a Worker with the given ID and returns a WorkerStub which may be used to invoke the Worker.

Worker Loader implements isolate caching

The loader implements caching of isolates. When a new ID is seen for the first time, a new isolate is loaded. The isolate may be kept warm in memory for a while. If later invocations request the same ID, the existing isolate may be returned again, rather than create a new one. However, there is no guarantee: a later call with the same ID may instead start a new isolate from scratch.

WorkerCode structure: compatibilityDate

WorkerCode.compatibilityDate is a required string field specifying the compatibility date for the Worker. This has the same meaning as the compatibility_date setting in a Wrangler config file.

WorkerCode structure: compatibilityFlags

WorkerCode.compatibilityFlags is an optional string array field containing compatibility flags augmenting the compatibility date. This has the same meaning as the compatibility_flags setting in a Wrangler config file.

WorkerCode structure: allowExperimental

WorkerCode.allowExperimental is an optional boolean field. If true, experimental compatibility flags are permitted in compatibilityFlags. To set this, the worker calling the loader must itself have the compatibility flag 'experimental' set. Experimental flags cannot be enabled in production.

WorkerCode modules field supports multiple formats

WorkerCode.modules is a Record<string, string | Module> mapping module names to their contents. If the module content is a plain string, the module name must have a file extension indicating its type: either .js or .py. Module content can also be specified as an object: {js: string} for JavaScript ES modules, {cjs: string} for CommonJS, {py: string} for Python, {text: string} for importable string value, {data: ArrayBuffer} for importable ArrayBuffer, or {json: object} for importable JSON-serializable object.

WorkerCode globalOutbound controls network access

WorkerCode.globalOutbound is an optional field of type ServiceStub | null that controls whether the dynamic Worker has access to the network. If not specified, the default is to inherit the parent's network access. If set to null, the dynamic Worker is totally cut off from the network and both fetch() and connect() will throw exceptions. globalOutbound can also be set to any service binding, including service bindings in the parent worker's env as well as loopback bindings from ctx.exports.

WorkerCode env field provides custom bindings

WorkerCode.env is an object field providing the environment object to the dynamic Worker. It may contain structured clonable types and Service Bindings (including loopback bindings from ctx.exports). This is how you provide custom bindings to the Worker.

WorkerCode tails field for Tail Workers

WorkerCode.tails is an optional ServiceStub[] field specifying one or more Tail Workers which will observe console logs, errors, and other details about the dynamically-loaded worker's execution. A tail event will be delivered to the Tail Worker upon completion of a request to the dynamically-loaded Worker.

Worker Loader Wrangler configuration

To add a dynamic worker loader binding to a worker, add it to the Wrangler config under the worker_loaders field: {"worker_loaders": [{"binding": "LOADER"}]}

Worker Loader get() returns synchronously

The get() method returns a WorkerStub synchronously; you do not have to await it. If the Worker is not loaded yet, requests made to the stub will wait for the Worker to load before being delivered. If loading fails, the request will throw an exception.

Worker Loader ID-based caching best practices

Because of Worker Loader caching, the callback should always return exactly the same content when called for the same ID. If anything about the content changes, a new ID must be used. Best practices include using IDs of the form <worker-name>:<version-number> where the version number increments with code changes, or computing IDs based on a hash of the code and config so any change results in a new ID.

Worker Loader requests may go to different isolates

It is never guaranteed that two requests will go to the same isolate. Even if you use the same WorkerStub to make multiple requests, they could execute in different isolates.

getEntrypoint() method on WorkerStub

WorkerStub has a getEntrypoint() method that returns the Worker's entrypoint and can be used to send requests to it. You can also get non-default entrypoints by calling getEntrypoint(entrypointName, {props: value}) where the props value is delivered to the entrypoint.

Worker Loader basic usage example

let id = "foo"; // Get the isolate with the given ID, creating it if no such isolate exists yet. let worker = env.LOADER.get(id, async () => { // If the isolate does not already exist, this callback is invoked to fetch // the isolate's Worker code. return { compatibilityDate: "2025-06-01", // Specify the worker's code (module files). mainModule: "foo.js", modules: { "foo.js": "export default {\n" + " fetch(req, env, ctx) { return new Response('Hello'); }\n" + "}\n", }, // Specify the dynamic Worker's environment (`env`). This is specified // as a JavaScript object, exactly as you want it to appear to the // child Worker. It can contain basic serializable types as well as // Service Bindings (see below). env: { SOME_ENV_VAR: 123, }, // To block the worker from talking to the internet using `fetch()` or // `connect()`, set `globalOutbound` to `null`. You can also set this // to any service binding, to have calls be intercepted and redirected // to that binding. globalOutbound: null, }; }); // Now you can get the Worker's entrypoint and send requests to it. let defaultEntrypoint = worker.getEntrypoint(); await defaultEntrypoint.fetch("http://example.com"); // You can get non-default entrypoints as well, and specify the // `ctx.props` value to be delivered to the entrypoint. let someEntrypoint = worker.getEntrypoint("SomeEntrypointClass", { props: { someProp: 123 }, });

Worker Loader globalOutbound with ctx.exports example

import { WorkerEntrypoint } from "cloudflare:workers"; export class Greeter extends WorkerEntrypoint { fetch(request) { return new Response(`Hello, ${this.ctx.props.name}!`); } } export default { async fetch(request, env, ctx) { let worker = env.LOADER.get("alice", () => { return { // Redirect the worker's global outbound to send all requests // to the `Greeter` class, filling in `ctx.props.name` with // the name "Alice", so that it always responds "Hello, Alice!". globalOutbound: ctx.exports.Greeter({ props: { name: "Alice" } }), // ... code ... }; }); return worker.getEntrypoint().fetch(request); }, };

Worker Loader custom binding with ctx.exports example

import { WorkerEntrypoint } from "cloudflare:workers"; // Implement a binding which can be called by the dynamic Worker. export class Greeter extends WorkerEntrypoint { greet() { return `Hello, ${this.ctx.props.name}!`; } } export default { async fetch(request, env, ctx) { let worker = env.LOADER.get("alice", () => { return { env: { // Provide a binding which has a method greet() which can be called // to receive a greeting. The binding knows the Worker's name. GREETER: ctx.exports.Greeter({ props: { name: "Alice" } }), }, // ... code ... }; }); return worker.getEntrypoint().fetch(request); }, };

Worker Loader Tail Workers example

import { WorkerEntrypoint } from "cloudflare:workers"; export default { async fetch(request, env, ctx) { let worker = env.LOADER.get("alice", () => { return { // Send logs, errors, etc. to `LogTailer`. We pass `name` in the // `ctx.props` so that `LogTailer` knows what generated the logs. // (You can pass anything you want in `props`.) tails: [ctx.exports.LogTailer({ props: { name: "alice" } })], // ... code ... }; }); return worker.getEntrypoint().fetch(request); }, }; export class LogTailer extends WorkerEntrypoint { async tail(events) { let name = this.ctx.props.name; // Send the logs off to our log endpoint, specifying the worker name in // the URL. // // Note that `events` will always be an array of size 1 in this scenario, // describing the event delivered to the dynamically-loaded Worker. await fetch(`https://example.com/submit-logs/${name}`, { method: "POST", body: JSON.stringify(events), }); } }

Python Workers slower than JavaScript in dynamic isolates

While Dynamic Isolates support Python, Python Workers are much slower to start than JavaScript Workers, which may defeat some of the benefits of dynamic isolate loading. They may also be priced differently when Worker Loaders become generally available.

Worker Loader codeCallback invoked only when starting new isolate

The codeCallback is only invoked when the system determines it needs to start a new isolate and does not already have a copy of the code cached. This is an async callback, so the application can load the code from remote storage if desired.

Worker Loader in closed beta on Cloudflare

The Worker Loader API is available in local development with Wrangler and workerd. However, to run dynamic Workers on Cloudflare, you must sign up for the closed beta.

Alternatives to waitUntil: Tail Workers and Queues

For emitting logs or exceptions, Tail Workers are recommended as an alternative to ctx.waitUntil(). Even if a Worker throws an uncaught exception, the Tail Worker will execute, ensuring logs or exceptions are emitted regardless of invocation status. For performing work out-of-band without blocking the response, Cloudflare Queues provide reliable delivery and automatic retries.

ctx.exports provides loopback bindings for top-level exports

ctx.exports is available when the enable_ctx_exports compatibility flag is used. For each top-level export that extends WorkerEntrypoint or implements a fetch handler, ctx.exports automatically contains a Service Binding. For each top-level export that extends DurableObject and has been configured with storage via a migration, ctx.exports automatically contains a Durable Object namespace binding. No external configuration is required; ctx.exports is populated automatically from top-level exports.

ctx.tracing provides custom spans API for observability

ctx.tracing provides access to the custom spans API for creating user-defined trace spans. It is the same object available via import { tracing } from 'cloudflare:workers'. Tracing must be enabled on the Worker for spans to be recorded. The tracing object exposes an enterSpan method that takes a span name and an async callback function.

Context API availability in handlers and WorkerEntrypoint

The Context API is exposed as the third parameter in all handlers, including the fetch() handler as fetch(request, env, ctx). It is also available as a class property of the WorkerEntrypoint class as this.ctx. The Context API is not available in Durable Objects; instead, Durable Objects have a Durable Object State object available as this.ctx.

ctx.waitUntil() extends Worker lifetime for background work

ctx.waitUntil() extends the lifetime of a Worker, allowing work to continue after a response is returned. It accepts a Promise which the Workers runtime will continue executing even after the handler returns. This is useful for logging, analytics, cache writes, and other work that does not need to block the response. If the client is still receiving the response, including streamed response bodies, the Worker remains active without ctx.waitUntil(). If the response depends on the work, await it before returning the response.

ctx.waitUntil() has 30-second time limit after invocation end

For HTTP-triggered Workers, ctx.waitUntil() can extend execution for up to 30 seconds after the response is sent or the client disconnects. This is not a limit on total wall time of an HTTP request. The 30-second time limit is shared across all ctx.waitUntil() calls within the same request. If any Promises have not settled after 30 seconds, they are canceled. When ctx.waitUntil tasks are canceled, the warning 'waitUntil() tasks did not complete within the allowed time after invocation end and have been cancelled.' is logged to Workers Logs and attached Tail Workers.

Multiple ctx.waitUntil() calls behave like Promise.allSettled

ctx.waitUntil() can be called multiple times. Similar to Promise.allSettled, even if a promise passed to one ctx.waitUntil call is rejected, promises passed to other ctx.waitUntil() calls will still continue to execute.

ctx.passThroughOnException enables fail-open pattern

ctx.passThroughOnException() allows a Worker to fail open and pass a request through to an origin server when the Worker throws an unhandled exception. This is useful when using Workers as a layer in front of an existing service. It protects against uncaught code exceptions but does not mitigate failures such as exceeding CPU or memory limits. If an exception occurs after the body has been consumed, ctx.passThroughOnException() cannot send the body again due to streaming bodies not being buffered.

Pitfall: ctx.passThroughOnException cannot resend consumed request bodies

The Workers runtime uses streaming for request and response bodies and does not buffer the body. If an exception occurs after the body has been consumed, passThroughOnException() cannot send the body again. For Workers that proxy requests to an origin, avoid relying on the runtime fallback when the origin fetch() fails. If the origin fetch() throws after consuming the request body, the fallback request may reach the origin without the original body and fail with an unrelated 4xx error. Best practice is to catch origin fetch errors and return a 5xx response instead.

TypeScript support for ctx.exports and ctx.props types

If using TypeScript, use the wrangler types command to auto-generate types for the project. The generated types will ensure ctx.exports is typed correctly. When declaring an entrypoint class that accepts props, declare it as extends WorkerEntrypoint<Env, Props>, where Props is the type of ctx.props.

ctx.waitUntil() example for caching responses

Example showing ctx.waitUntil() for caching: ctx.waitUntil(caches.default.put(request, res.clone())); This caches the response without blocking the return of the response to the client.

ctx.tracing.enterSpan() example for custom tracing

Example demonstrating ctx.tracing.enterSpan() for custom trace spans: export default { async fetch(request, env, ctx) { return ctx.tracing.enterSpan('handleRequest', async (span) => { span.setAttribute('url.path', new URL(request.url).pathname); const data = await env.MY_KV.get('key'); return new Response(data); }); }, }; This creates a span named 'handleRequest', sets an attribute for the URL path, and performs KV operations within the span.

ctx.passThroughOnException example for fail-open pattern

Example demonstrating ctx.passThroughOnException(): export default { async fetch(request, env, ctx) { ctx.passThroughOnException(); try { return await fetch(request); } catch (error) { console.error('Origin fetch failed', error); return new Response('Bad Gateway', { status: 502 }); } }, }; This enables fail-open behavior where unhandled exceptions pass the request through to the origin, while caught errors return a 502 response.

Note: ctx.waitUntil not needed for Durable Objects normal behavior

Do not use ctx.waitUntil() to keep a Durable Object alive during normal request or RPC handling. Durable Objects remain active while handling requests, RPC calls, response streams, WebSockets, or pending I/O. DurableObjectState.waitUntil() exists for API compatibility and is not needed for this behavior.

Alarm handler in Durable Objects

The alarm handler is used to handle scheduled alarms in Cloudflare Workers using the Durable Objects alarm API. It allows Durable Objects to execute code at scheduled times.

Worker-to-Worker fetch requires Service bindings or global_fetch_strictly_public flag

Worker-to-Worker fetch requests are possible with Service bindings or by enabling the global_fetch_strictly_public compatibility flag.

Fetch API must run in handler, not global scope

Asynchronous tasks such as fetch must be executed within a handler. If you try to call fetch() within global scope, your Worker will throw an error.

Give your agent this brain