The ctx.exports API contains automatically-configured bindings corresponding to your Worker's top-level exports. For each top-level export extending WorkerEntrypoint, ctx.exports will contain a Service Binding by the same name, and for each export extending DurableObject (and for which storage has been configured via a migration), ctx.exports will contain a Durable Object namespace binding. This means you no longer have to configure these bindings explicitly in wrangler.jsonc/wrangler.toml.
Example:
import { WorkerEntrypoint } from "cloudflare:workers";export class Greeter extends WorkerEntrypoint { greet(name) { return `Hello, ${name}!`; }}export default { async fetch(request, env, ctx) { let greeting = await ctx.exports.Greeter.greet("World") return new Response(greeting); }}
You can now more precisely control your HTTP DLP policies by specifying whether to scan the request or response body, helping to reduce false positives and target specific data flows.
In the Gateway HTTP policy builder, you will find a new selector called Body Phase. This allows you to define the direction of traffic the DLP engine will inspect:
Request Body: Scans data sent from a user's machine to an upstream service. This is ideal for monitoring data uploads, form submissions, or other user-initiated data exfiltration attempts.
Response Body: Scans data sent to a user's machine from an upstream service. Use this to inspect file downloads and website content for sensitive data.
For example, consider a policy that blocks Social Security Numbers (SSNs). Previously, this policy might trigger when a user visits a website that contains example SSNs in its content (the response body). Now, by setting the Body Phase to Request Body, the policy will only trigger if the user attempts to upload or submit an SSN, ignoring the content of the web page itself.
All policies without this selector will continue to scan both request and response bodies to ensure continued protection.
Email security relies on your submissions to continuously improve our detection models. However, we often receive submissions in formats that cannot be ingested, such as incomplete EMLs, screenshots, or text files.
To ensure all customer feedback is actionable, we have launched two new features to manage invalid submissions sent to our team and user submission aliases:
Email Notifications: We now automatically notify users by email when they provide an invalid submission, educating them on the correct format. To disable notifications, go to Settings ↗︎ > Invalid submission emails and turn the feature off.
Invalid Submission dashboard: You can quickly identify which users need education to provide valid submissions so Cloudflare can provide continuous protection.
You can run multiple Workers in a single dev command by passing multiple config files to wrangler dev:
wrangler dev --config ./web/wrangler.jsonc --config ./api/wrangler.jsonc
Previously, if you ran the command above and then also ran wrangler dev for a different Worker, the Workers running in separate wrangler dev sessions could not communicate with each other. This prevented you from being able to use Service Bindings ↗︎ and Tail Workers ↗︎ in local development, when running separate wrangler dev sessions.
Now, the following works as expected:
# Terminal 1: Run your application that includes both Web and API workerswrangler dev --config ./web/wrangler.jsonc --config ./api/wrangler.jsonc# Terminal 2: Run your auth worker separatelywrangler dev --config ./auth/wrangler.jsonc
These Workers can now communicate with each other across separate dev commands, regardless of your development setup.
./api/src/index.tsjs
export default { async fetch(request, env) { // This service binding call now works across dev commands const authorized = await env.AUTH.isAuthorized(request); if (!authorized) { return new Response("Unauthorized", { status: 401 }); } return new Response("Hello from API Worker!", { status: 200 }); },};
Browser-based RDP with Cloudflare Access is now generally available for all Cloudflare customers. It enables secure, remote Windows server access without VPNs or RDP clients.
Since we announced our open beta, we've made a few improvements:
More robust error messaging on the login page to help you if you encounter an issue.
Worldwide keyboard support. Whether your day-to-day is in Portuguese, Chinese, or something in between, your browser-based RDP experience will look and feel exactly like you are using a desktop RDP client.
Cleaned up some other miscellaneous issues, including but not limited to enhanced support for Entra ID accounts and support for usernames with spaces, quotes, and special characters.
As a refresher, here are some benefits browser-based RDP provides:
Control how users authenticate to internal RDP resources with single sign-on (SSO), multi-factor authentication (MFA), and granular access policies.
Record who is accessing which servers and when to support regulatory compliance requirements and to gain greater visibility in the event of a security event.
Eliminate the need to install and manage software on user devices. You will only need a web browser.
Reduce your attack surface by keeping your RDP servers off the public Internet and protecting them from common threats like credential stuffing or brute-force attacks.
The ratelimit binding is now stable and recommended for all production workloads. Existing deployments using the unsafe binding will continue to function to allow for a smooth transition.
In workers-rs ↗︎, Rust panics were previously non-recoverable. A panic would put the Worker into an invalid state, and further function calls could result in memory overflows or exceptions.
Now, when a panic occurs, in-flight requests will throw 500 errors, but the Worker will automatically and instantly recover for future requests.
This ensures more reliable deployments. Automatic panic recovery is enabled for all new workers-rs deployments as of version 0.6.5, with no configuration required.
Fixing Rust Panics with Wasm Bindgen
Rust Workers are built with Wasm Bindgen, which treats panics as non-recoverable. After a panic, the entire Wasm application is considered to be in an invalid state.
This function clears all internal state related to the Wasm VM, and updates all function bindings in place to reference the new WebAssembly instance.
One other necessary change here was associating Wasm-created JS objects with an instance identity. If a JS object created by an earlier instance is then passed into a new instance later on, a new "stale object" error is specially thrown when using this feature.
Layered Solution
Building on this new Wasm Bindgen feature, layered with our new default panic handler, we also added a proxy wrapper to ensure all top-level exported class instantiations (such as for Rust Durable Objects) are tracked and fully reinitialized when resetting the Wasm instance. This was necessary because
the workerd runtime will instantiate exported classes, which would then be associated with the Wasm instance.
This approach now provides full panic recovery for Rust Workers on subsequent requests.
Of course, we never want panics, but when they do happen they are isolated and can be investigated further from the error logs - avoiding broader service disruption.
WebAssembly Exception Handling
In the future, full support for recoverable panics could be implemented without needing reinitialization at all, utilizing the WebAssembly Exception Handling ↗︎
proposal, part of the newly announced WebAssembly 3.0 ↗︎ specification. This would allow unwinding panics as normal JS errors, and concurrent requests would no longer fail.
You can now route private traffic to Cloudflare Tunnel based on a hostname or domain, moving beyond the limitations of IP-based routing. This new capability is free for all Cloudflare One customers.
Previously, Tunnel routes could only be defined by IP address or CIDR range. This created a challenge for modern applications with dynamic or ephemeral IP addresses, often forcing administrators to maintain complex and brittle IP lists.
What’s new:
Hostname & Domain Routing: Create routes for individual hostnames (e.g., payroll.acme.local) or entire domains (e.g., *.acme.local) and direct their traffic to a specific Tunnel.
Simplified Zero Trust Policies: Build resilient policies in Cloudflare Access and Gateway using stable hostnames, making it dramatically easier to apply per-resource authorization for your private applications.
Precise Egress Control: Route traffic for public hostnames (e.g., bank.example.com) through a specific Tunnel to enforce a dedicated source IP, solving the IP allowlist problem for third-party services.
No More IP Lists: This feature makes the workaround of maintaining dynamic IP Lists for Tunnel connections obsolete.
We recently increased the available disk space from 8 GB to 20 GB for all plans. Building on that improvement, we’re now doubling the CPU power available for paid plans — from 2 vCPU to 4 vCPU.
These changes continue our focus on making Workers Builds faster and more reliable.
Metric
Free Plan
Paid Plans
CPU
2 vCPU
4 vCPU
Performance Improvements
Fast build times: Even single-threaded workloads benefit from having more vCPUs
2x faster multi-threaded builds: Tools like esbuild ↗︎ and webpack ↗︎ can now utilize additional cores, delivering near-linear performance scaling
All other build limits — including memory, build minutes, and timeout remain unchanged.
To prevent the accidental exposure of applications, we've updated how Worker preview URLs (<PREVIEW>-<WORKER_NAME>.<SUBDOMAIN>.workers.dev) are handled. We made this change to ensure preview URLs are only active when intentionally configured, improving the default security posture of your Workers.
One-Time Update for Workers with workers.dev Disabled
We performed a one-time update to disable preview URLs for existing Workers where the workers.dev subdomain was also disabled.
Because preview URLs were historically enabled by default, users who had intentionally disabled their workers.dev route may not have realized their Worker was still accessible at a separate preview URL. This update was performed to ensure that using a preview URL is always an intentional, opt-in choice.
If your Worker was affected, its preview URL (<PREVIEW>-<WORKER_NAME>.<SUBDOMAIN>.workers.dev) will now direct to an informational page explaining this change.
How to Re-enable Your Preview URL
If your preview URL was disabled, you can re-enable it via the Cloudflare dashboard by navigating to your Worker's Settings page and toggling on the Preview URL.
Alternatively, you can use Wrangler by adding the preview_urls = true setting to your Wrangler file and redeploying the Worker.
{ "preview_urls": true}
preview_urls = true
Note: You can set preview_urls = true with any Wrangler version that supports the preview URL flag (v3.91.0+). However, we recommend updating to v4.34.0 or newer, as this version defaults preview_urls to false, ensuring preview URLs are always enabled by explicit choice.
Zero Trust Dashboard has a brand new, AI-powered search functionality. You can search your account by resources (applications, policies, device profiles, settings, etc.), pages, products, and more.
Ask Cloudy — You can also ask Cloudy, our AI agent, questions about Cloudflare Zero Trust. Cloudy is trained on our developer documentation and implementation guides, so it can tell you how to configure functionality, best practices, and can make recommendations.
Cloudy can then stay open with you as you move between pages to build configuration or answer more questions.
Find Recents — Recent searches and Cloudy questions also have a new tab under Zero Trust Overview.
Three months ago we announced the public beta of remote bindings for local development. Now, we're excited to say that it's available for everyone in Wrangler, Vite, and Vitest without using an experimental flag!
With remote bindings, you can now connect to deployed resources like R2 buckets and D1 databases while running Worker code on your local machine. This means you can test your local code changes against real data and services, without the overhead of deploying for each iteration.
Example configuration
To enable remote bindings, add "remote" : true to each binding that you want to rely on a remote resource running on Cloudflare:
{ "name": "my-worker", // Set this to today's date "compatibility_date": "2026-10-11", "r2_buckets": [ { "bucket_name": "screenshots-bucket", "binding": "screenshots_bucket", "remote": true, }, ],}
name = "my-worker"# Set this to today's datecompatibility_date = "2026-10-11"[[r2_buckets]]bucket_name = "screenshots-bucket"binding = "screenshots_bucket"remote = true
When remote bindings are configured, your Worker still executes locally, but all binding calls are proxied to the deployed resource that runs on Cloudflare's network.
We’re excited to announce that Email security customers can now choose their preferred mail processing location directly from the UI when onboarding a domain. This feature is available for the following onboarding methods: MX, BCC, and Journaling.
What’s new
Customers can now select where their email is processed. The following regions are supported:
Germany
India
Australia
Global processing remains the default option, providing flexibility to meet both compliance requirements or operational preferences.
How to use it
When onboarding a domain with MX, BCC, or Journaling:
Select the desired processing location (Germany, India, or Australia).
The UI will display updated processing addresses specific to that region.
For MX onboarding, if your domain is managed by Cloudflare, you can automatically update MX records directly from the UI.
Availability
This feature is available across these Email security packages:
Advantage
Enterprise
Enterprise + PhishGuard
What’s next
We’re expanding the list of processing locations to match our Data Localization Suite (DLS) footprint, giving customers the broadest set of regional options in the market without the complexity of self-hosting.
Magic WAN and WARP Connector users can now securely route their DNS traffic to the Gateway resolver without exposing traffic to the public Internet.
Routing DNS traffic to the Gateway resolver allows DNS resolution and filtering for traffic coming from private networks while preserving source internal IP visibility. This ensures Magic WAN users have full integration with our Cloudflare One features, including Internal DNS and hostname-based policies.
To configure DNS filtering, change your Magic WAN or WARP Connector DNS settings to use Cloudflare's shared resolver IPs, 172.64.36.1 and 172.64.36.2. Once you configure DNS resolution and filtering, you can use Source Internal IP as a traffic selector in your resolver policies for routing private DNS traffic to your Internal DNS.
We've updated our "Built with Cloudflare" button to make it easier to share that you're building on Cloudflare with the world. Embed it in your project's README, blog post, or wherever you want to let people know.
Deploying static site to Workers is now easier. When you run wrangler deploy [directory] or wrangler deploy --assets [directory] without an existing configuration file, Wrangler CLI now guides you through the deployment process with interactive prompts.
Before and after
Before: Required remembering multiple flags and parameters
After: Simple directory deployment with guided setup
wrangler deploy dist# Interactive prompts handle the rest as shown in the example flow below
What's new
Interactive prompts for missing configuration:
Wrangler detects when you're trying to deploy a directory of static assets
Prompts you to confirm the deployment type
Asks for a project name (with smart defaults)
Automatically sets the compatibility date to today
Automatic configuration generation:
Creates a wrangler.jsonc file with your deployment settings
Stores your choices for future deployments
Eliminates the need to remember complex command-line flags
Example workflow
# Deploy your built static sitewrangler deploy dist# Wrangler will prompt:✔ It looks like you are trying to deploy a directory of static assets only. Is this correct? … yes✔ What do you want to name your project? … my-astro-site# Automatically generates a wrangler.jsonc file and adds it to your project:{ "name": "my-astro-site", "compatibility_date": "2025-09-09", "assets": { "directory": "dist" }}# Next time you run wrangler deploy, this will use the configuration in your newly generated wrangler.jsonc filewrangler deploy
Requirements
You must use Wrangler version 4.24.4 or later in order to use this feature
Now, Magic WAN customers can configure a custom IKE ID for their IPsec tunnels. Customers that are using Magic WAN and a VeloCloud SD-WAN device together can utilize this new feature to create a high availability configuration.
All bidirectional tunnel health check return packets are accepted by any Magic on-ramp.
Previously, when a Magic tunnel had a bidirectional health check configured, the bidirectional health check would pass when the return packets came back to Cloudflare over the same tunnel that was traversed by the forward packets.
There are SD-WAN devices, like VeloCloud, that do not offer controls to steer traffic over one tunnel versus another in a high availability tunnel configuration.
Now, when a Magic tunnel has a bidirectional health check configured, the bidirectional health check will pass when the return packet traverses over any tunnel in a high availability configuration.
You can now upload up to 100,000 static assets per Worker version
Paid and Workers for Platforms users can now upload up to 100,000 static assets per Worker version, a 5x increase from the previous limit of 20,000.
Customers on the free plan still have the same limit as before — 20,000 static assets per version of your Worker
The individual file size limit of 25 MiB remains unchanged for all customers.
This increase allows you to build larger applications with more static assets without hitting limits.
Wrangler
To take advantage of the increased limits, you must use Wrangler version 4.34.0 or higher.
Earlier versions of Wrangler will continue to enforce the previous 20,000 file limit.
You can now manage Workers, Versions, and Deployments as separate resources with a new, resource-oriented API (Beta).
This new API is supported in the Cloudflare Terraform provider ↗︎ and the Cloudflare Typescript SDK ↗︎, allowing platform teams to manage a Worker's infrastructure in Terraform, while development teams handle code deployments from a separate repository or workflow. We also designed this API with AI agents in mind, as a clear, predictable structure is essential for them to reliably build, test, and deploy applications.
This API worked for creating a basic Worker, uploading all of its code, and deploying it immediately — but came with challenges:
A Worker couldn't exist without code: To create a Worker, you had to upload its code in the same API request. This meant platform teams couldn't provision Workers with the proper settings, and then hand them off to development teams to deploy the actual code.
Several endpoints implicitly created deployments: Simple updates like adding a secret or changing a script's content would implicitly create a new version and immediately deploy it.
Updating a setting was confusing: Configuration was scattered across eight endpoints with overlapping responsibilities. This ambiguity made it difficult for human developers (and even more so for AI agents) to reliably update a Worker via API.
Scripts used names as primary identifiers: This meant simple renames could turn into a risky migration, requiring you to create a brand new Worker and update every reference. If you were using Terraform, this could inadvertently destroy your Worker altogether.
After: Three resources with clear boundaries
The new API introduces cleaner resource management with three core resources: Worker, Versions, and Deployment.
All endpoints now use simple JSON payloads, with script content embedded as base64-encoded strings -- a more consistent and reliable approach than the previous multipart/form-data format.
Worker: The parent resource representing your application. It has a stable UUID and holds persistent settings like name, tags, and logpush. You can now create a Worker to establish its identity and settings before any code is uploaded.
Version: An immutable snapshot of your code and its specific configuration, like bindings and compatibility_date. Creating a new version is a safe action that doesn't affect live traffic.
Deployment: An explicit action that directs traffic to a specific version.
Why this matters
You can now create Workers before uploading code
Workers are now standalone resources that can be created and configured without any code. Platform teams can provision Workers with the right settings, then hand them off to development teams for implementation.
Example: Typescript SDK
// Step 1: Platform team creates the Worker resource (no code needed)const worker = await client.workers.beta.workers.create({ name: "payment-service", account_id: "...", observability: { enabled: true, },});// Step 2: Development team adds code and creates a version laterconst version = await client.workers.beta.workers.versions.create(worker.id, { account_id: "...", main_module: "worker.js", compatibility_date: "$today", bindings: [ /*...*/ ], modules: [ { name: "worker.js", content_type: "application/javascript+module", content_base64: Buffer.from(scriptContent).toString("base64"), }, ],});// Step 3: Deploy explicitly when readyconst deployment = await client.workers.scripts.deployments.create(worker.name, { account_id: "...", strategy: "percentage", versions: [ { percentage: 100, version_id: version.id, }, ],});
Example: Terraform
If you use Terraform, you can now declare the Worker in your Terraform configuration and manage configuration outside of Terraform in your Worker's wrangler.jsonc file and deploy code changes using Wrangler.
resource "cloudflare_worker" "my_worker" { account_id = "..." name = "my-important-service"}# Manage Versions and Deployments here or outside of Terraform# resource "cloudflare_worker_version" "my_worker_version" {}# resource "cloudflare_workers_deployment" "my_worker_deployment" {}
Deployments are always explicit, never implicit
Creating a version and deploying it are now always explicit, separate actions - never implicit side effects. To update version-specific settings (like bindings), you create a new version with those changes. The existing deployed version remains unchanged until you explicitly deploy the new one.
# Step 1: Create a new version with updated settings (doesn't affect live traffic)POST /workers/workers/{id}/versions{ "compatibility_date": "$today", "bindings": [ { "name": "MY_NEW_ENV_VAR", "text": "new_value", "type": "plain_text" } ], "modules": [...]}# Step 2: Explicitly deploy when ready (now affects live traffic)POST /workers/scripts/{script_name}/deployments{ "strategy": "percentage", "versions": [ { "percentage": 100, "version_id": "new_version_id" } ]}
Settings are clearly organized by scope
Configuration is now logically divided: Worker settings (like name and tags) persist across all versions, while Version settings (like bindings and compatibility_date) are specific to each code snapshot.
# Version settings (the "code")POST /workers/workers/{id}/versions{ "compatibility_date": "$today", "bindings": [...], "modules": [...]}
/workers API endpoints now support UUIDs (in addition to names)
The /workers/workers/ path now supports addressing a Worker by both its immutable UUID and its mutable name.
# Both work for the same WorkerGET /workers/workers/29494978e03748669e8effb243cf2515 # UUID (stable for automation)GET /workers/workers/payment-service # Name (convenient for humans)
This dual approach means:
Developers can use readable names for debugging.
Automation can rely on stable UUIDs to prevent errors when Workers are renamed.
Terraform can rename Workers without destroying and recreating them.
The pre-existing Workers REST API remains fully supported. Once the new API exits beta, we'll provide a migration timeline with ample notice and comprehensive migration guides.
Existing Terraform resources and SDK methods will continue to be fully supported through the current major version.
While the Deployments API currently remains on the /scripts/ endpoint, we plan to introduce a new Deployments endpoint under /workers/ to match the new API structure.
Starting December 1, 2025, list endpoints for the Cloudflare Tunnel API and Zero Trust Networks API will no longer return deleted tunnels, routes, subnets and virtual networks by default. This change makes the API behavior more intuitive by only returning active resources unless otherwise specified.
No action is required if you already explicitly set is_deleted=false or if you only need to list active resources.
The default behavior of the is_deleted query parameter will be updated.
Scenario
Previous behavior (before December 1, 2025)
New behavior (from December 1, 2025)
is_deleted parameter is omitted
Returns active & deleted tunnels, routes, subnets and virtual networks
Returns only active tunnels, routes, subnets and virtual networks
Action required
If you need to retrieve deleted (or all) resources, please update your API calls to explicitly include the is_deleted parameter before December 1, 2025.
To get a list of only deleted resources, you must now explicitly add the is_deleted=true query parameter to your request:
# Example: Get ONLY deleted Tunnelscurl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/tunnels?is_deleted=true" \ -H "Authorization: Bearer $API_TOKEN"# Example: Get ONLY deleted Virtual Networkscurl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/teamnet/virtual_networks?is_deleted=true" \ -H "Authorization: Bearer $API_TOKEN"
Following this change, retrieving a complete list of both active and deleted resources will require two separate API calls: one to get active items (by omitting the parameter or using is_deleted=false) and one to get deleted items (is_deleted=true).
Why we’re making this change
This update is based on user feedback and aims to:
Create a more intuitive default: Aligning with common API design principles where list operations return only active resources by default.
Reduce unexpected results: Prevents users from accidentally operating on deleted resources that were returned unexpectedly.
Improve performance: For most users, the default query result will now be smaller and more relevant.
Also through customer feedback, we have created a new additive role to allow Email security Analyst to create, edit, and delete Email security policies, without needing to provide access via the Email Configuration Admin role. This role is called Email security Policy Admin, which can read all settings, but has write access to allow policies, trusted domains, and blocked senders.
This feature is available across these Email security packages:
We're excited to share a new AI feature, the WARP diagnostic analyzer ↗︎, to help you troubleshoot and resolve WARP connectivity issues faster. This beta feature is now available in the Cloudflare One dashboard ↗︎ to all users. The AI analyzer makes it easier for you to identify the root cause of client connectivity issues by parsing remote captures of WARP diagnostic logs. The WARP diagnostic analyzer provides a summary of impact that may be experienced on the device, lists notable events that may contribute to performance issues, and recommended troubleshooting steps and articles to help you resolve these issues. Refer to WARP diagnostics analyzer (beta) to learn more about how to maximize using the WARP diagnostic analyzer to troubleshoot the WARP client.
The DEX MCP server is an AI tool that allows customers to ask a question like, "Show me the connectivity and performance metrics for the device used by carly@acme.com", and receive an answer that contains data from the DEX API.
Any Cloudflare One customer using a Free, Pay-as-you-go, or Enterprise account can access the DEX MCP Server. This feature is available to everyone.
Customers can test the new DEX MCP server in less than one minute. To learn more, read the DEX MCP server documentation.