Skip to content

Changelog

New updates and improvements at Cloudflare.

Route across a pool of models with model aliases

AI Gateway now supports model aliases. A model alias is a pool of models that your application calls by one name, such as custom/support-fast. AI Gateway tries the models in the order you set and falls back to the next one if a request fails, or uses smart routing to choose a model for each request.

Because your application only references the alias, you can swap models or change the routing algorithm on your gateway without redeploying. Create and manage aliases on your gateway's Routing page, alongside dynamic routes.

To call an alias through the REST API, use its name as the model. For example, send this body to /accounts/{account_id}/ai/run:

{
	"model": "custom/support-fast",
	"input": {
		"messages": [{ "role": "user", "content": "Reply with a short greeting." }]
	}
}

Include the cf-aig-gateway-id header to select the gateway where you created the alias. Aliases are scoped to individual gateways.

For setup instructions and routing options, refer to Model aliases.

Granular access controls for the top Personal Agents

The Configure AI bot policies setting is now named AI Crawler and Agent access policies.

Personal agents act on a person's behalf, fetching information or browsing in response to a request. The updated policies let you set actions for the top Personal Agents individually. This gives you control over agent access while allowing visitors to use agents to find answers or compare products using your site's content.

Customize how Personal Agents access your site via Security > Settings > AI Crawler and Agent access policies.

AI Crawler and Agent access policies dialog showing the Agents policy and individual Personal Agents settings

For more information, check out our blog ↗︎ or refer to our documentation for AI Crawler and Agent access policies.

Block data entry with Browser Isolation without losing search, copy, and zoom (beta)

Isolation policies now support a third keyboard option in beta: Allow read-only actions. Previously, the keyboard setting was binary — allow all input or block everything. With Allow read-only actions, you can block data entry while preserving the built-in browser actions your users depend on.

In Allow read-only actions mode, users can still find in page, select all, copy, print, and zoom. All other keyboard input is blocked from reaching the isolated page. Copy and print remain subject to their own policy settings, so the controls compose instead of overriding each other. For example, setting the keyboard to Allow read-only actions and copy to Do not allow lets users search and zoom but prevents them from copying content.

To use this feature, set Keyboard to Allow read-only actions in your isolation policy settings. Via the API, set keyboard to enable_read_only_actions in the biso_admin_controls object with version set to v2.

For more information, refer to Keyboard.

Agents SDK now supports Pi 1.5 with fewer storage writes and lower memory use

Agents SDK v0.33.0 upgrades PiHarness to Pi 1.5 ↗︎. The release reduces storage transactions while streaming, improves throughput across many sessions, and reduces memory use when streaming large tool calls.

Performance improvements

  • Far fewer storage writes while streaming. Pi stores streamed answers and tool output in batches, within a second of each update, instead of on every update. Over SQLite, this cuts storage transactions by about 27x for long answers and 5.7x for turns with parallel tools, and CPU by about a quarter.
  • Higher throughput across many sessions. Pi's scheduler no longer rechecks every conversation on each commit. In a SQLite benchmark with 2,048 sessions, one Pi harness went from 88 to 459 agent runs per second.
  • Less memory on large answers. Streaming a 500 KB tool call used to take about 20 seconds of CPU and a 100 MB heap. Pi now appends new text instead of copying it on every update.

Streaming updates remain visible immediately, but are persisted in batches. With the default settings, a crash can lose up to about one second of streamed progress. Refer to Recovery to configure this interval.

Session and tool updates

  • A view of each session. session.watch() replaces session.events(). It returns the newest transcript entries and the session's live state, such as the answer being streamed, running tools, and why the last run ended without an answer.
  • Continue without adding a message. The new session.continue() API starts a new run using the existing transcript, for example after a model error or when a run reaches its turn limit.
  • Turn limit. defaults.maxTurns caps the tool rounds a run can take in new sessions.
  • Tasks that keep crashing end. Pi now ends a task cut off by its restart limit instead of parking it. retry() and the parked status are removed.
  • Browser in Pi's code mode. Scripts in Pi's code mode can call browserTool and pass its screenshots to image(). browserTool also stops when the harness aborts its call.

Continue an unanswered conversation

For an existing session and submission operationId, check the result before offering a continuation. For example, after resolving a model error:

const result = await session.wait(operationId);

if (result.status === "unanswered" && result.reason === "model_error") {
	const receipt = await session.continue({
		operationId: `${operationId}:continue`,
	});
	const continued = await session.wait(receipt.operationId);
	console.log(continued.status, continued.text);
}
const result = await session.wait(operationId);

if (result.status === "unanswered" && result.reason === "model_error") {
	const receipt = await session.continue({
		operationId: `${operationId}:continue`,
	});
	const continued = await session.wait(receipt.operationId);
	console.log(continued.status, continued.text);
}

This starts a new run without appending a user message. The session must be idle. If the transcript already ends in an answer, the operation returns unanswered with reason nothing_to_answer. Refer to Work with sessions.

Upgrade

Once a conversation runs on Pi 1.5, Pi 1.4 cannot read it. After upgrading, roll forward to fix deployment issues rather than rolling back to Pi 1.4.

Update callers of session.events() to use session.watch(), and remove uses of retry() and the parked status. Refer to the Pi Durable 1.5.0 changelog ↗︎ for the full list of breaking changes.

The Agents SDK v0.33.0 changelog ↗︎ has step-by-step upgrade instructions. Point your coding agent at them and upgrade today:

New AI Gateways require authentication

New AI Gateways now require authentication to prevent unauthorized requests. Once authentication is on, you cannot turn it off through the dashboard or API.

When you create a new AI Gateway through the API, authentication is on by default. You can leave out the authentication field or set it to true. If you set it to false, the API returns HTTP 400.

When you update an existing gateway, leaving out authentication keeps its current setting. If you try to turn off authentication after it is on, the API returns HTTP 400.

Existing gateways with authentication turned off can continue without it. You can turn it on in your gateway settings or include authentication: true in a gateway update request:

{
	"authentication": true
}

Before turning authentication on, configure HTTP clients to send a valid Cloudflare API token. Requests through Workers bindings remain pre-authenticated.

For setup instructions and supported authorization headers, refer to AI Gateway authentication.

See which AI assistants act for your users in Account Abuse Protection

Account Abuse Protection now shows when a recognized AI assistant makes a login or sign up request, and which account it was acting for.

  • Population overview: See which AI assistants are active across your users and how many accounts use them.
  • Account activity: Every login and sign up event shows whether an AI assistant made the request, and which one.
  • AI assistant filters: filter accounts by number of AI assistant events or number of AI assistants.

Use this to investigate and mitigate a single account without blocking an assistant for everyone else who relies on it, and to tune your agent settings in AI Crawler and Agent access policies.

AI assistant visibility covers login and sign up events only. Requests from assistants that Cloudflare does not recognize appear as ordinary traffic.

For more information, refer to AI assistants.

Crawl results include URL outcomes and robots.txt diagnostics

Browser Run /crawl results now include more detailed diagnostics. Each URL record can include an outcome that identifies the specific processing result, such as success, robots_disallowed, timeout, or page_error.

The job-level robots array reports the robots.txt state for up to 50 origins encountered by the crawl. Each entry includes the origin, whether usable rules were available, and the HTTP status when the crawler received a response.

{
	"robots": [
		{
			"origin": "https://example.com",
			"state": "available",
			"status": 200
		}
	],
	"records": [
		{
			"url": "https://example.com/docs/",
			"status": "completed",
			"outcome": "success"
		}
	]
}

For field definitions and all possible outcome values, refer to URL outcomes and robots.txt diagnostics.

Request metrics breakdown by region and HTTP error code

You can now compare regional activity and errors by HTTP status code on the Metrics page for a R2 bucket in the Cloudflare dashboard.

Go to Bucket metrics ↗

Compare regions

Use Request Distribution by Region to compare request activity and filter by writes, reads, errors, or rate-limited errors (429).

R2 request distribution showing a globe, a list of regions, and the Writes filter

Inspect errors

Use Errors by Status Code to compare error counts and trends.

R2 error counts and time series grouped by HTTP status code

To troubleshoot errors, refer to the R2 error code reference.

Zero Wire, a hub for investigating critical Internet vulnerabilities

Cloudflare Radar now includes Zero Wire ↗︎, a hub for investigating critical Internet vulnerabilities and threats. Each briefing separates confirmed facts from open questions, lists remediation steps, and shows what Cloudflare observes about the threat.

Zero Wire page listing briefings under Needs attention, each with its recommended action, CVEs, tags, why it needs attention, and what to do now

Briefings

Briefings are grouped by urgency. Needs attention covers active incidents, new guidance, or unresolved scope that security teams should review now. Reference keeps stable briefings available, even if not every affected system has been patched. Each card shows the recommended action and summarizes what happened, why it matters, and what to do.

Each briefing page expands on the card with an update chronology and an overview, followed by:

  • What to do now: remediation steps, plus a prompt to copy into an AI agent with access to your infrastructure, asking for an evidence-based assessment of affected systems and exposure.
  • Cloudflare coverage: the Cloudflare products that protect against the threat, and any impact on Cloudflare's own services.
  • Evidence and sources: vendor advisories, CVE records, the CISA Known Exploited Vulnerabilities (KEV) catalog, and Radar charts, such as requests matching the related Cloudflare WAF rules.
Zero Wire briefing for the Linux IPv4 TCP use-after-free, showing its recommended action, CVE, tags, update chronology, overview, and table of contents

Follow updates

Search briefings by CVE, name, or tag, or browse every briefing with a given tag. To follow new briefings and updates, subscribe to the Zero Wire RSS feed ↗︎ or to the feed of a single tag. New briefings also appear in the Caught on Radar ↗︎ section of the Radar homepage.

Send questions or feedback from any briefing page, or at radar@cloudflare.com.

For more details, read the blog post ↗︎ or visit Zero Wire ↗︎.

WAF Release - 2026-11-03

This release introduces updates to the underlying rule expressions for PHP out-of-memory (OOM) vulnerabilities CVE-2026-109618, CVE-2026-109619 and CVE-2026-115560. The improvements are iterative changes based on reports from Security Researchers as part of PHP Capture the Flag (CTF) challenge ↗︎.

RulesetRule IDLegacy Rule IDDescriptionPrevious ActionNew ActionComments
Cloudflare Free RulesetN/APHP Remote Code Execution Attack (CVE-2026-109618, CVE-2026-109619) #2BlockBlockRule detection updated.
Cloudflare Free RulesetN/APHP Remote Code Execution Attack (CVE-2026-109618, CVE-2026-109619) #3BlockBlockRule detection updated.
Cloudflare Managed RulesetN/APHP Remote Code Execution Attack (CVE-2026-109618, CVE-2026-109619) #2BlockBlockRule detection updated.
Cloudflare Managed RulesetN/APHP Remote Code Execution Attack (CVE-2026-109618, CVE-2026-109619) #3BlockBlockRule detection updated.
Cloudflare Managed RulesetN/AphpMyAdmin - Authentication BypassN/ADisabledThis is a new detection.

WAF Release - Scheduled changes for 2026-11-10

Announcement DateRelease DateRelease BehaviorLegacy Rule IDRule IDDescriptionComments
2026-10-122026-11-10LogN/ABroken Access Control - Directory Traversal (Beta)

This rule will be merged into the original rule "Broken Access Control - Directory Traversal" (ID: ).

2026-11-032026-11-10LogN/AGeneric Rules - Dangerous File Upload

This is a new detection.

AI Search billing postponed to December 1, 2026, and default sync interval is now 24 hours

Billing postponed to December 1, 2026

AI Search billing has been postponed by one month and now begins on December 1, 2026, instead of November 1, 2026. You will not be charged for AI Search usage before December 1, 2026. Pricing and included usage are unchanged.

For rates and included usage, refer to Limits & pricing.

Default sync interval is now 24 hours

The default sync interval for AI Search instances is changing from 6 hours to 24 hours. You can still choose any supported interval, from 15 minutes to 24 hours, with the Sync interval setting in your instance settings or the sync_interval field in the API.

For details, refer to Sync interval.

New Account Abuse Protection Dashboard

Account Abuse Protection customers in Early Access can now investigate login and sign up activity in a dedicated dashboard under Security > Account Abuse Protection.

  • Population overview: See total login and sign up events, unique accounts, IPs and devices, top countries and ASNs, and leaked credential check results. Filter accounts by signals such as leaked credential events and unique IPs to find the accounts that need review.
  • Individual Account overview: Review a single Hashed User ID's activity, including its top networks, locations and devices, and an event log with the Ray ID for each event. Mitigate the account with a Security Rule on its Hashed User ID.
  • New roles: The Account Abuse Protection role grants access to the dashboard. Account Abuse Protection PII role grants access to the dashboard as well as account-level PII, such as email address, and is required to create or edit Logpush jobs that include PII. The dashboard includes all login and sign up events from the date the feature was enabled.

For more information, refer to Account Abuse Protection.

Organize and authorize Access service tokens with tags

You can now assign key-value tags to Access service tokens and use those tags to organize credentials or control application access. Each token supports up to five tags, such as environment: production or team: payments.

Add or edit tags when you create or update a token in the dashboard or service token API. You can search and filter by tag on the Service Tokens page. Tags also appear in Resource Tagging, where you can query them alongside other tagged resources.

The Service Token Tag policy selector matches valid tokens with an exact key-value pair. Use it in a Service Auth policy to authorize tokens by environment or team without listing each token individually. For example, this API policy configuration accepts valid tokens tagged environment: production:

{
	"name": "Production service tokens",
	"decision": "non_identity",
	"include": [
		{
			"service_token_tag": {
				"key": "environment",
				"value": "production"
			}
		}
	]
}

For setup instructions, refer to Tag service tokens and Authorize service tokens by tag.

Evaluate Flagship flags locally

Flagship bindings now evaluate flags against a local flag store during local development, instead of calling your remote app. You can develop offline and test flag changes without affecting production. This applies to wrangler dev, the Cloudflare Vite plugin, the Vitest integration, and cf dev.

The local store starts empty, so evaluations return the default value you pass in code. Add and manage local flags in any of these ways:

  • Wrangler — Add --local to wrangler flagship flags commands, such as create, update, and evaluate. To copy all flags from your remote app, run npx wrangler flagship flags pull <APP_ID>.
  • Local Explorer — Create, edit, toggle, and evaluate flags in Local Explorer while your dev server runs.
  • cf CLI — Add --local to cf flagship commands.

To keep evaluating against your remote app instead, set remote: true on the binding.

The local flag store requires Wrangler v4.135.0 or @cloudflare/vite-plugin v1.56.0 or later. Flagship in Local Explorer requires Wrangler v4.148.0 or @cloudflare/vite-plugin v1.63.0 or later.

Refer to Flagship local development for details.

Workers will use the new module registry by default on November 17

Starting November 17, 2026, JavaScript Workers with a compatibility date of 2026-11-17 or later will use the new module registry by default. You will no longer need the new_module_registry flag for these dates. Python Workers keep using the legacy registry.

The module registry finds and loads JavaScript modules in your Worker. We announced the new registry in September 2026 ↗︎. It improves compatibility with JavaScript standards and Node.js. In Workers using Node.js compatibility, you can use require() to load ES modules. The module and its dependencies must not use top-level await.

You can also use import.meta to get information about the current module and find the URL of another module without loading it:

src/index.jsjs
export default {
	fetch() {
		return Response.json({
			moduleUrl: import.meta.url,
			isEntrypoint: import.meta.main,
			helperUrl: import.meta.resolve("./helper.js"),
		});
	},
};
src/index.tsts
export default {
	fetch(): Response {
		return Response.json({
			moduleUrl: import.meta.url,
			isEntrypoint: import.meta.main,
			helperUrl: import.meta.resolve("./helper.js"),
		});
	},
} satisfies ExportedHandler;

When deployed with src/index.ts as the unbundled entrypoint, isEntrypoint is true. helperUrl is a URL within your Worker bundle. Resolving the URL does not check whether the module exists or load it over the network. Build tools may transform import.meta. To try this example directly, refer to unbundled deployments.

Existing Workers keep their current behavior until you change their compatibility date or flags. To try the new registry before November 17, keep your current date and add new_module_registry to your compatibility flags.

Before updating, check your dependencies for invalid import attributes and changes to require() behavior. The new registry rejects invalid import attributes. Calls to require() also fail if the module or any of its dependencies use top-level await. To keep the legacy registry with a compatibility date of 2026-11-17 or later, add legacy_module_registry.

For migration details, refer to the new module registry compatibility flag, bundling documentation, and Node.js compatibility documentation.

Request.signal will be enabled by default in Workers on November 17

Starting November 17, 2026, Workers with a compatibility date of 2026-11-17 or later will receive client disconnection events through request.signal by default. Use these events to stop unnecessary work when a client leaves. You will no longer need the enable_request_signal compatibility flag for these dates.

We introduced this feature in May 2025. You can log cancellations, clean up resources, or cancel operations that accept an AbortSignal.

For example, this Worker logs a client disconnection and cancels an outgoing request:

src/index.jsjs
export default {
	async fetch(request) {
		request.signal.addEventListener(
			"abort",
			() => {
				console.log("Client disconnected");
			},
			{ once: true },
		);

		return fetch("https://example.com/slow-response", {
			signal: request.signal,
		});
	},
};
src/index.tsts
export default {
	async fetch(request): Promise<Response> {
		request.signal.addEventListener(
			"abort",
			() => {
				console.log("Client disconnected");
			},
			{ once: true },
		);

		return fetch("https://example.com/slow-response", {
			signal: request.signal,
		});
	},
} satisfies ExportedHandler;

Existing Workers keep their current behavior until you change their compatibility date or flags. To try this feature before November 17, keep your current date and add enable_request_signal to your compatibility flags.

With a compatibility date of 2026-11-17 or later, add disable_request_signal to opt out. This change does not enable request_signal_passthrough. Pass the signal explicitly, as the example does.

For more information, refer to the Request API and the Request.signal compatibility flag.

Inspect provisioned users and groups with the SCIM population viewer

The SCIM population viewer lets you inspect the users and groups provisioned to Cloudflare One by each identity provider. You can check which resources Cloudflare has received without making API requests or opening a support ticket.

In Zero Trust > Integrations > Identity providers, select a user or group count in SCIM resources to open the viewer. You can:

  • Search users by username, email, name, or resource ID, and groups by name or resource ID.
  • Inspect resource attributes in formatted or JSON views.
  • View group members and compare Cloudflare and IdP resource IDs with provisioning logs.
  • Delete individual resources from the Cloudflare SCIM population when you have edit permission.
SCIM users table with search controls and blurred personal information

The viewer shows provisioned resources rather than provisioning event history. Use SCIM provisioning logs to investigate failed requests. Existing SCIM deprovisioning and policy behavior remain unchanged.

For dashboard instructions and API examples, refer to View SCIM users and groups.

Audit Logs v2: Account analytics

Audit Logs v2 now includes analytics for account-level audit logs in the Cloudflare dashboard. The Actions over time chart separates successful and failed actions for the selected time range.

Summary cards show Total actions, Unique actors, Products impacted, and Failure rate. Select a card to investigate action types, authentication methods, top actors, top products, or failed actions. You can apply or exclude values as filters to update both the analytics and audit log table.

Account analytics in Audit Logs v2

Account analytics are not available for organization-level audit logs.

For more information, refer to the account analytics documentation.

Browser Run now runs Chrome 152

Browser Run now runs Chrome 152 by default. Your sessions get current web platform features, rendering fixes, and security patches. You do not need to change your code.

This release also includes the following improvements:

  • Updated default User-Agent. The default User-Agent for Quick Actions now reports Chrome 152 instead of Chrome 119. If you allowlist or match the Browser Run User-Agent, update your rules. You can still set your own value with the userAgent parameter. Refer to Automatic request headers.
  • Better site compatibility. Quick Actions requests now look more like requests from a regular Chrome browser, so fewer sites block them.
  • Large response headers. Pages that return large response headers now load correctly.
  • Updated root certificates. Browser Run removed distrusted root certificates from its trust store.
  • Absolute links. /links now returns absolute URLs, and links-only crawls now follow relative links.
  • Better Markdown output. /markdown and crawl Markdown output now keep code block languages.
  • Clearer errors. Quick Actions that time out now return a consistent error. Outbound Workers that throw an exception now return an HTTP error to the browser.

For more information, refer to the Browser Run documentation.

D1 will enforce a maximum query result size of 50 MB

Beginning Wednesday, November 4, 2026, D1 will enforce a maximum query result size of 50 MB. Queries that return a result larger than 50 MB will fail and return the following error:

D1 query result exceeded the maximum response size limit of 50 MB

The 50 MB limit covers the 99.999th percentile of requests across D1, so most D1 users will not be impacted.

Import and export operations via the REST API are not subject to this limit and will continue to work as they do today.

If your queries return large results, reduce the result size before the enforcement date. For example, select only the columns you need instead of using SELECT *, and paginate large result sets with LIMIT and OFFSET.

For more information, refer to D1 limits and the D1 error list.

Cloudflare WAN supports regional Gateway HTTP inspection

Cloudflare WAN traffic can now use a Gateway processing region with Regional Services. HTTPS traffic enters a Cloudflare data center (that may be outside the selected region) via an IPsec or GRE tunnel, or through Direct CNI, and remains encrypted until Gateway forwards it to the selected region for TLS decryption and HTTP inspection. This feature gives organizations control over where their sensitive traffic is processed, supporting their data sovereignty goals.

This feature requires unified routing. The processing region applies to Gateway HTTP traffic and does not apply to Gateway DNS or network policy processing.

Contact your account team to configure a processing region. For supported regions, configuration details, and limitations, refer to Data residency for Cloudflare One.

New DNS records experience is now the default for everyone

The new DNS records experience announced in May is now the default for all users on all plans, including Enterprise. The classic DNS records page has been retired and is no longer available in the Cloudflare dashboard.

Changing a record's type

When the new experience first launched, it did not support changing the type of an existing DNS record. Based on your feedback, we have since added this, so you can now change a record's type (for example, from A to CNAME) directly from the DNS records page. Under the hood, the dashboard uses the batch DNS records endpoint for this.

Questions or feedback

If you run into an issue with the new experience, contact your account team or Cloudflare Support.

Durable Objects now defer code updates by default

Durable Objects can stay active across requests, allowing you to run long-running agents, maintain long-lived WebSocket connections and coordinate state across many clients. This is possible because each Durable Object is globally unique, and this means it must run only one version of your code at a time. Previously, when you deployed a change to your Durable Objects code, that change would be applied immediately, which could interrupt in-flight work and terminate open connections.

Durable Objects now defer code updates by default. When you deploy, an active Durable Object can keep running its current code for up to 5 minutes (300 seconds) while it waits to hibernate. This gives in-flight work time to finish. WebSocket connections that use the Hibernation API remain connected when an object adopts new code after hibernating.

For an active Durable Object, a code update follows this flow:

flowchart TD
    accTitle: Code updates for an active Durable Object
    accDescr: By default, an active object can keep running its current code until it hibernates or the delay ends. After hibernating, it starts on new code on the next request. If the delay ends first, or immediate mode is selected, it resets and adopts the new code. Deferral is best effort.
    A["You deploy new code"] -->|"Default: deferred"| B["The object can keep running<br/>its current code"]
    B --> C{"Hibernates before<br/>the delay ends?"}
    C -->|Yes| D["Starts on the new code<br/>on the next request"]
    C -->|No| E["The object resets<br/>and adopts the new code"]
    A -.->|"Override: immediate"| E

To change the delay, add code_update_strategy to durable_objects in your Wrangler configuration:

{
	"durable_objects": {
		"bindings": [
			{
				"name": "CHAT_ROOM",
				"class_name": "ChatRoom",
			},
		],
		"code_update_strategy": {
			"mode": "deferred",
			"max_delay": 60,
		},
	},
}
[[durable_objects.bindings]]
name = "CHAT_ROOM"
class_name = "ChatRoom"

[durable_objects.code_update_strategy]
mode = "deferred"
max_delay = 60

max_delay is in seconds, from 0 to 86400 (24 hours), with millisecond precision. Omit it to use the default of 300 seconds.

To set the strategy for a single deployment, pass --durable-objects-code-update-mode with immediate or deferred <duration>. For example, apply an update right away during an incident, or when your deployment tooling calls a Durable Object right after deploying and needs the new code:

npx wrangler versions deploy <VERSION_ID>@100% --durable-objects-code-update-mode immediate

A deferred code update is best effort and does not guarantee that every operation finishes. The object can still reset before max_delay is reached, for example during a Cloudflare runtime update.

For more information, including how this interacts with gradual deployments and the REST API, refer to Durable Objects code updates.