Skip to content

Changelog

New updates and improvements at Cloudflare.

Deploy larger Workers — up to 64 MiB for both free and paid plans

You can now deploy Workers with larger dependencies, heavier frameworks, and more code without hitting size limits.

When you deploy a Worker, Wrangler bundles your code and compresses it before uploading. Previously, Cloudflare checked that compressed size and rejected deploys over 3 MB (Free) or 10 MB (Paid). That limit has been removed. Cloudflare now only checks the uncompressed size of your bundle, which is 64 MiB across all plans.

To check your Worker's bundle size before deploying:

wrangler deploy --outdir bundled/ --dry-run
Total Upload: 259.61 KiB / gzip: 47.23 KiB

The Total Upload value is your uncompressed bundle size. This is what counts against the 64 MiB limit. The gzip value is shown for reference but is no longer a limit.

For more information, refer to the Worker size limits documentation.

New in Images: text rasterization and updates to the binding

We've added more ways to manage and manipulate images with the Images binding. Here's what's new:

Render text into an image. Output a string of text into its own image or draw it over another image.

  • Use the .text() method to rasterize text with the Images binding.
  • Style content using the font, size, and color options.
  • The draw array in cf.image now accepts a text key.

Manage hosted images without an API token.

  • Metadata filtering: Pass filter.metadata to .list() to return images by custom metadata. Match a bounded range by setting two operators in one condition, for example, priority: { gte: 2, lte: 5 }.
  • Server-side signing: Get a signed URL for a private image with .signedUrl().
  • User uploads: Create a Direct Creator Upload link with .createDirectUpload() so that a client can upload an image to your storage.

Set headers in a single call.

  • Pass a headers option to .response() to set headers without rebuilding the Response.
  • Content-Type is always taken from the optimized image and can't be overridden by a specified header.
  • Set Cache-Control with Workers Cache to cache your optimized image at the edge.

For more information, refer to Optimize with Workers, Draw overlays and watermarks, and Manage hosted images with Workers.

Create multiple Cloudflare Tunnel and Cloudflare Mesh routes at once

You can now create multiple Cloudflare Tunnel and Cloudflare Mesh routes from the Routes page in a single action, instead of submitting one route at a time.

Creating multiple Cloudflare Tunnel and Cloudflare Mesh routes at once from the Routes page

When creating a route, you can now:

  • Add multiple destinations at once — Enter a comma-separated list of CIDR ranges or hostnames to create several routes of the same type and connector together.
  • Queue up multiple routes — Select Add another to stage additional routes, including different types or connectors, before creating them all in one action.
  • Retry only what failed — If some routes in a batch fail (for example, an invalid CIDR), the routes that were created successfully are removed from the form automatically, so you only need to fix and resubmit the ones that failed.

The same Routes UI already supports bulk creation for Cloudflare WAN static routes, so you can add multiple WAN destinations or queue up several WAN routes before creating them together as well.

Go to Routes ↗

For setup steps, refer to Add routes.

Run Cursor Cloud Agents on Cloudflare via self-hosted machines

Cursor self-hosted machines let you run Cursor Cloud Agents on Cloudflare. Each assigned session runs in its own isolated environment backed by Cloudflare Containers.

Cursor Cloud Agents environment selector showing the cloudflare-pool self-hosted machine pool

Cursor hosts the agent loop, inference, and planning. Cloudflare runs commands, file edits, repository operations, and other tools inside infrastructure that you control. The open-source Cursor Cloudflare Workers template deploys the Worker, Durable Object namespace, container application, R2 bucket binding, and cron trigger used by the integration.

To get started, refer to Run Cursor Cloud Agents on Cloudflare via self-hosted machines.

Python Workers now support WSGI web frameworks like Django and Flask

Python web frameworks following the Web Server Gateway Interface (WSGI) or Asynchronous Server Gateway Interface (ASGI) specification can now be used in Python Workers.

Using web frameworks with Python Workers

Based on the web framework you are using, you can use either wsgi or asgi from the workers module.

WSGI frameworks

For WSGI frameworks like Django or Flask:

from workers import wsgi

from django.core.wsgi import get_wsgi_application

app = get_wsgi_application()
Default = wsgi.entrypoint(app)

The wsgi.entrypoint is equivalent to creating a WorkerEntrypoint class and using the wsgi.fetch method. If you want more control over the WorkerEntrypoint class, you can do so:

from workers import wsgi, WorkerEntrypoint

class Default(WorkerEntrypoint):
    async def fetch(self, request):
        return await wsgi.fetch(app, request, self.env)

ASGI frameworks

For ASGI frameworks like FastAPI or Starlette:

from workers import asgi

from fastapi import FastAPI

app = FastAPI()
Default = asgi.entrypoint(app)

For more information about using individual web frameworks, refer to the packages documentation in Python Workers.

AI Gateway consolidates monthly usage invoice line items and standardizes model names

AI Gateway monthly usage invoices, issued at the beginning of each month for the previous month's usage, now show a single total cost for each model. These invoices no longer break out input and output token quantities and unit prices into separate line items. This change does not apply to invoices for AI Gateway credit purchases.

For example, an invoice that previously included these separate line items:

  • anthropic claude-haiku-4-5-20251001 Input Tokens: 40,000 tokens at $0.000001 ($0.04)
  • anthropic claude-haiku-4-5-20251001 Output Tokens: 24,000 tokens at $0.000005 ($0.12)

The updated invoice includes one line item: anthropic/claude-haiku-4.5: $0.16.

AI Gateway has also standardized model names across invoices and logs. Model variants that previously appeared with provider-specific version suffixes now use a consistent provider/model identifier.

For more information, refer to the Unified Billing documentation and AI Gateway logging documentation.

D1 enforces free tier daily query limits

Beginning September 1, 2026, D1 queries on the Workers Free plan will fail when an account exceeds the daily row read or row write limits. Queries via the Workers Binding API and the REST API will return errors until the limit resets at midnight UTC. Stored data is not affected.

You will receive email alerts when the daily limit is reached. The following errors indicate that a limit has been exceeded:

Error Description
Your account has exceeded D1's free tier daily row read limit. Upgrade to a paid plan or wait until tomorrow (midnight UTC) to continue. The account has reached its daily row read limit.
Your account has exceeded D1's free tier daily row write limit. Upgrade to a paid plan or wait until tomorrow (midnight UTC) to continue. The account has reached its daily row write limit.

Inspect database query activity before the enforcement date to identify queries that may exceed these limits. To reduce row reads, add indexes to tables and review queries that perform full table scans. If usage requires higher limits after optimization, upgrade to a Workers Paid plan.

For more information on D1 errors and how to handle them, refer to the D1 error list.

Crawl endpoint now respects the Content Signals `use` directive

The /crawl endpoint now respects the use directive of the Content Signals standard, letting site owners express the maximum level at which their content may be used.

You can declare your intended level with the new contentUse parameter. Allowed values, from least to most permissive, are reference and full, and the default is full. If a target site's robots.txt sets a use level that is more restrictive than your declared contentUse, the crawl request is rejected with a 400 error.

curl -X POST 'https://api.cloudflare.com/client/v4/accounts/{account_id}/browser-rendering/crawl' \
  -H 'Authorization: Bearer <apiToken>' \
  -H 'Content-Type: application/json' \
  -d '{
    "url": "https://example.com",
    "contentUse": "reference",
    "formats": ["markdown"]
  }'

For more information, refer to Content Signals in the /crawl endpoint documentation.

Z.ai GLM-5.3 now available on Workers AI

@cf/zai-org/glm-5.3 is now available on Workers AI. It is Z.ai's flagship agentic coding model, built for long-running, tool-driven development workflows rather than single-turn chat.

GLM-5.3 uses the same base model as GLM-5.2, with every gain coming from post-training. The results are substantial on coding and agentic benchmarks: Z.ai reports a 50% improvement over GLM-5.2 on its in-house Z.ai Code Bench, and calls GLM-5.3 the most capable open-weights model for coding. On public benchmarks, it scores 88.2 on Terminal Bench 2.1 (up from 81.0), 28.3 on Terminal Bench 3.0 — open-source state of the art, up from 4.6 — 66.9 on DeepSWE (up from 46.2), 78.1 on FrontierSWE (up from 67.5), and 42.5 on SWE-Marathon (up from 19.4). It is also the top-scoring model in Z.ai's comparisons on CyberGym for vulnerability discovery (84.5) and on long-horizon automation tasks like AutomationBench (48.2).

The price-to-performance ratio is the compelling part. On Workers AI, GLM-5.3 costs the same as GLM-5.2 — $1.40 per M input tokens, $0.26 per M cached input tokens, and $4.40 per M output tokens — while roughly doubling GLM-5.2's scores on long-horizon benchmarks like SWE-Marathon, and improving them by more than 6x on Terminal Bench 3.0.

GLM-5.3 requires the Workers Paid plan or prepaid AI Gateway credits.

Use GLM-5.3 through the Workers AI binding (env.AI.run()), the REST API, the OpenAI-compatible endpoint, or AI Gateway.

For more information, refer to the GLM-5.3 model page and pricing.

Durable Objects can use up to ten Dynamic Workers concurrently

Durable Objects can have up to ten distinct Dynamic Workers with in-flight requests, increased from four. This limit applies across all concurrent requests to the same Durable Object because they share an input/output (I/O) context. Other Workers can have up to four distinct Dynamic Workers with in-flight requests per request.

Multiple in-flight requests to the same Dynamic Worker count as one toward this limit.

For more information, refer to Dynamic Workers limits.

New Workers AI text generation models in AI Search

AI Search now supports six additional Workers AI models for text generation:

Model Context window (tokens)
@cf/deepseek-ai/deepseek-v4-flash-0731 1,048,576
@cf/deepseek-ai/deepseek-v4-pro-0813 1,048,576
@cf/openai/gpt-oss-120b 128,000
@cf/openai/gpt-oss-20b 128,000
@cf/qwen/qwen3.8-27b 262,144
@cf/moonshotai/kimi-k2.7-code 262,144

These models run on Workers AI, so they do not require an additional provider key. Select a model when creating or updating an AI Search instance in the dashboard or through the API.

For the full list of supported models, refer to Supported models.

Create app-scoped API tokens for Flagship

You can now create app-scoped API tokens for Flagship. These tokens grant access only to the Flagship apps you select, instead of every app in the account.

When you create a custom token, open the resource dropdown (it defaults to Entire Account) and select Specified Flagship apps. Then choose the app and a Flagship App permission: Evaluate, Read, or Write. Account-wide Flagship Evaluate, Read, and Write permissions still exist when you need access to every app.

Use app-scoped tokens in trusted server-side environments, such as Wrangler, CI, or a backend service that should only touch one app.

To create a token, refer to API tokens or open the app-scoped token form in the dashboard.

Z.ai GLM-5.3 Flash now available on Workers AI

@cf/zai-org/glm-5.3-flash is now available on Workers AI. It is the first natively multimodal model in the GLM-5 series, built on a Mixture-of-Experts architecture with 320B total parameters and 18B active per token.

GLM-5.3 Flash is the first GLM-family model on Workers AI to support multimodal inputs. It outperforms GLM-5.2 across benchmarks and real-world workloads at a lower price, while approaching Claude Opus 4.8 on coding and agentic benchmarks.

GLM-5.3 Flash requires the Workers Paid plan or prepaid AI Gateway credits.

Use GLM-5.3 Flash through the Workers AI binding (env.AI.run()), the REST API, the OpenAI-compatible endpoint, or AI Gateway.

For more information, refer to the GLM-5.3 Flash model page and pricing.

Store larger custom metadata values in AI Search

AI Search supports larger custom metadata values within a shared 10 KiB metadata envelope for each vector. The envelope includes AI Search system metadata and JSON overhead, so it is not a per-field limit. The first 64 UTF-8 bytes of each indexed string remain filterable.

For details, refer to Metadata attributes.

Prevent Durable Object alarm retries when using `ctx.abort()`

By default, an alarm interrupted by ctx.abort() retries after the Durable Object resets. Pass { retryAlarm: false } when the alarm should stop instead:

src/index.jsjs
import { DurableObject } from "cloudflare:workers";

export class CleanupTask extends DurableObject {
	async alarm() {
		await this.ctx.storage.deleteAll();

		this.ctx.abort("Cleanup complete", { retryAlarm: false });
	}
}
src/index.tsts
import { DurableObject } from "cloudflare:workers";

export class CleanupTask extends DurableObject {
	async alarm(): Promise<void> {
		await this.ctx.storage.deleteAll();

		this.ctx.abort("Cleanup complete", { retryAlarm: false });
	}
}

For example, an alarm that deletes its storage can use this option to avoid repeating the cleanup or re-running the Durable Object constructor.

Alarms can run concurrently with other requests to the same Durable Object. If another request calls ctx.abort() while an alarm is running, the retryAlarm option on that call also controls whether the alarm retries.

The default retry prevents an unrelated request from permanently canceling the alarm. Set retryAlarm: false on every abort path that should stop an in-progress alarm, not only on calls from the alarm handler. Existing calls to ctx.abort() keep retrying alarms.

For local development, retryAlarm requires Wrangler 4.126.0 or later.

For more information, refer to ctx.abort().

Choose OAuth scopes for Wrangler and the Cloudflare API MCP server

Wrangler and the Cloudflare API MCP server now use optional OAuth scopes. During authorization, you can choose which optional scopes to grant instead of approving every scope requested by each client.

The consent dialog now includes the option to edit the permissions you grant to Wrangler or the Cloudflare API MCP server:

OAuth consent dialog with an Edit Permissions button

You can then choose which specific permissions to grant:

OAuth permission editor with controls for individual scopes

Required scopes remain selected. Choosing fewer optional scopes limits each tool's access to the permissions needed for your workflow.

If a command or tool call needs a scope that you declined, reauthorize the client and grant that scope.

For more information, refer to wrangler login and Edit optional permissions.

Web Analytics improves soft navigation measurement for Single Page Applications (SPAs)

Cloudflare Web Analytics (Real User Monitoring) is rolling out accuracy improvements to client-side soft navigations. Update: this update is complete as of 2026-09-04.

This change may alter the volume of reported pageviews and visits in the dashboard and GraphQL API. The reported Largest Contentful Paint (LCP) metric may also fluctuate. The extent of these variances depend on your front-end architecture and visitor traffic patterns.

Single Page Applications (SPAs)—such as websites built with React, Angular, Vue, or Svelte—predominantly use soft navigations. Soft navigations avoid fully unloading the current page and rendering the next one from scratch as visitors navigate.

Any client-side navigation counts as a soft navigation, including navigations intercepted by the Navigation API or triggered by the History API. This means a non-SPA website can have soft navigation activity if its implementation uses these APIs.

The main improvement comes from Google Chrome's new Soft Navigation API. It natively measures Largest Contentful Paint (LCP) on soft navigations, removing a blind spot in perceived loading speed across pageviews.

We've extended our navigationType values to segment these different types of navigations:

navigationType New? Description
navigate Hard navigations that traditional websites (or "Multi Page Applications") perform when clicking links or submitting forms
soft-navigation Where the new Soft Navigation API is available and a visitor makes a client-side navigation, we record these events
routing-apis Where the native Soft Navigation API is unavailable (e.g. Safari, Firefox, older Chromium-based browsers), we fallback to measuring soft navigations using the Navigation API or History API. We cannot collect LCP for these, but the other Core Web Vitals are present.

Prior to this change, we only used History API and all navigations were bucketed into navigate.

For more information, refer to the Navigation Types and Web Analytics SPA documentation pages.

Run more headless browsers concurrently with Browser Run

Browser Run lets you automate headless browsers on Cloudflare's global network. Run full browser sessions for interactive workflows, or use Quick Actions for one-request tasks such as screenshots, PDFs, and capturing page content.

If you are on the Workers Paid plan, your default limits are now higher:

Limit Previous New
Concurrent browsers 120 200
New browser instances / second 1 3
Quick Actions requests / second 10 30

You can now run hundreds of browser sessions in parallel, launch new browsers faster, and process three times as many Quick Actions per second. These published limits are defaults, not maximums. If your workload needs more more concurrent browsers, request higher limits.

Use FUSE in local Containers development

Miniflare now automatically grants local Containers the Docker privileges required for Filesystem in Userspace (FUSE). This applies to wrangler dev, the Cloudflare Vite plugin, and direct Miniflare use.

Miniflare grants these privileges when the local Docker daemon runs inside a virtual machine (VM). This includes Docker engines on macOS and through Windows Subsystem for Linux (WSL). On Linux, Miniflare grants the privileges for local rootless Docker when /dev/fuse is available.

Rootful Docker on Linux does not support FUSE by default during local development. Miniflare does not grant FUSE privileges when the Docker daemon does not meet these conditions or cannot be inspected.

For requirements and troubleshooting, refer to FUSE support during local development. For a complete example, refer to Mount R2 buckets with FUSE.

View deployments for Durable Objects in the dashboard

Durable Object namespaces now have a Deployments tab in the Cloudflare dashboard, showing the versions of the backing Worker that are currently live and the traffic split between them.

The Deployments tab for a Durable Object namespace, showing two versions with their traffic %, requests/sec, error rate, and median wall time Go to Durable Objects ↗

A Durable Object namespace is backed by a Worker script, so its deployments are the same as that Worker's deployments. Previously, checking on a gradual deployment in progress for a Durable Object meant navigating to the backing Worker. The new tab surfaces that information directly on the namespace, alongside the metrics that matter for it: requests, error rate, and wall time per version.

The tab is read-only — promoting, rolling back, or splitting traffic on a deployment is still managed from the backing Worker's Deployments tab.

Actual vs. configured traffic split

The Traffic % column, for both Workers and Durable Objects, now shows the actual, observed traffic share for each version next to the percentage you configured. Previously, this column only showed the configured percentage. If you moved a deployment from 50/50 to 100% on a new version, the configured number updated immediately, but requests take time to catch up, and there was no way to tell how far along that shift was without checking metrics elsewhere.

The configured split assigns Worker versions to individual Durable Objects, not to individual requests. Because each Durable Object is pinned to the version it started on until you create a new deployment and some objects naturally receive more traffic than others, the observed split can differ from the configured one for as long as multiple versions are active.

Actual traffic share is calculated from the same GraphQL Analytics API data that powers other Workers and Durable Objects metrics, so standard ingestion delay and sampling apply. Durable Objects analytics can lag Workers analytics by several minutes, so a version's actual share may take a little longer to catch up after a change.

To view this, go to Workers & Pages > Durable Objects, select a namespace, then select the Deployments tab. For more on how gradual deployments work, refer to Gradual deployments.

Get 50% off GPT-5.6 Sol through AI Gateway

GPT-5.6 Sol is available through AI Gateway, and for a limited time you can use it at 50% off. If you are already using AI Gateway, point to the openai/gpt-5.6-sol model and the discounted pricing applies automatically — no promo code needed.

The promotion is available for Unified Billing users only (not Bring Your Own Keys). Load credits onto AI Gateway and start sending requests to openai/gpt-5.6-sol.

Discounted pricing during the promotion:

Usage Promotional price Standard price
Input $2.50 per 1M tokens $5 per 1M tokens
Output $15 per 1M tokens $30 per 1M tokens
Cache read $0.25 per 1M tokens $0.50 per 1M tokens

The promotion runs through September 18, 2026. After that date, GPT-5.6 Sol requests return to standard pricing.

For more details, refer to the Unified Billing documentation and the GPT-5.6 Sol model page.

@cloudflare/vitest-pool-workers is now @cloudflare/vitest-plugin

Version 1 of the Workers Vitest integration is published as @cloudflare/vitest-plugin. The package was formerly named @cloudflare/vitest-pool-workers.

The Vitest configuration API is unchanged. Existing projects must update the dependency name, package imports, and TypeScript types entries.

To migrate automatically, run:

npx @cloudflare/codemods vitest:pool-workers-to-vitest-plugin

The codemod updates your dependency, imports, and test TypeScript configuration. For manual migration steps, refer to Migrate to Vitest plugin.

For outbound request mocks in Workers tests, use the @msw/cloudflare integration. Refer to Mock outbound requests.

Configure origin application settings for Cloudflare Tunnel in the dashboard

You can now configure origin application settings directly in the Cloudflare dashboard when adding or editing a published application route for a Cloudflare Tunnel. These settings control how cloudflared connects to your origin server and were previously only available in the Cloudflare One dashboard or via local configuration files.

Configure origin application settings in the Cloudflare dashboard

When editing a published application, expand Additional application settings to configure parameters organized into three categories:

  • HTTP — Set a custom HTTP Host header or disable chunked encoding.
  • TLS — Configure origin server name, CA pool, TLS timeout, disable TLS verification, match SNI to host, or enable HTTP/2 to origin.
  • Connection — Tune connect timeout, keep-alive timeout, keep-alive connections, TCP keep-alive interval, proxy type, or disable Happy Eyeballs.
Go to Tunnels ↗

For the full list of origin parameters, refer to Origin parameters.

New `us` jurisdiction for R2

R2 now supports a us jurisdiction, which guarantees that bucket data is stored and processed within the United States. Use this jurisdiction when you need explicit US data residency guarantees.

Use the jurisdiction-specific S3 endpoint to create and access buckets in the us jurisdiction:

https://<ACCOUNT_ID>.us.r2.cloudflarestorage.com

To access a bucket in the us jurisdiction from Workers, set jurisdiction in your R2 binding:

{
	"r2_buckets": [
		{
			"binding": "MY_BUCKET",
			"bucket_name": "<YOUR_BUCKET_NAME>",
			"jurisdiction": "us"
		}
	]
}
[[r2_buckets]]
binding = "MY_BUCKET"
bucket_name = "<YOUR_BUCKET_NAME>"
jurisdiction = "us"

Once an R2 bucket is created, its jurisdiction cannot be changed.

For setup instructions and the full list of supported jurisdictions, refer to R2 data location.