Skip to content

Changelog

New updates and improvements at Cloudflare.

Pending I/O operations allow Durable Objects to continue long-running work without a connected client

Durable Objects remain active while handling a request from a connected client. This change applies when no client is connected, such as when an agent continues a submitted job after its client disconnects.

This behavior is the default for Workers with a compatibility date of 2026-10-01 or later. To use it with an earlier date, add the durable_object_io_tasks_prevent_eviction compatibility flag. To opt out, add the durable_object_io_tasks_do_not_prevent_eviction flag.

Pending service binding requests now keep Durable Objects running while they wait for a response. Pending calls to another Durable Object through remote procedure call (RPC) or fetch(), as well as this.ctx.container.monitor(), now also keep the Durable Object running.

Promises passed to this.ctx.waitUntil() and pending setTimeout() and setInterval() timers also receive this protection.

Previously, Cloudflare could shut down an idle Durable Object while one of these operations remained pending without a connected client. This could stop unfinished work.

This change helps you run long-running tasks such as agents. An agent can call tools through service bindings, coordinate with other Durable Objects, or wait for a container process without relying on the original client to remain connected.

Outbound fetch() requests to external services, TCP sockets, and outbound WebSockets already keep Durable Objects running.

Each pending operation prevents idle shutdown for up to 15 minutes. Starting another one later can extend the Durable Object's time in memory. The limit applies to each operation, not to the total time in memory.

Timeline of a service binding fetch, an RPC call, and monitor() each preventing eviction for up to 15 minutes

Duration charges continue while an operation prevents eviction.

For more information, refer to Lifecycle of a Durable Object.

Workers traces now automatically include JavaScript RPC session spans

Workers traces can now follow JavaScript RPC calls across Worker boundaries and into Durable Objects. Previously, a trace stopped at the caller's RPC boundary. The dashboard now shows the caller-side session and method calls alongside the callee invocation, nested calls, and callbacks into another Worker.

A session span covers the lifetime of a caller-side session and groups calls that reuse it. Individual call spans show each method invocation. Execution colors distinguish the Workers or Durable Object entrypoints involved, while arrows mark outgoing and incoming calls. Together, these details show where time was spent, which calls reused a session, and how returned stubs and callbacks fit into the request.

A Workers trace of a Worker-to-Worker RPC session, showing the session span, the caller's getCounter and increment call spans, and the callee's invocation and matching call spans

Enable tracing with one setting in your Wrangler configuration file:

{
  "$schema": "./node_modules/wrangler/config-schema.json",
  "observability": {
    "traces": {
      "enabled": true
    }
  }
}
[observability.traces]
enabled = true

Cloudflare records these spans automatically. You do not need to change your application code or add an observability SDK.

For supported spans and attributes, refer to Spans and attributes.

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.

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().

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.

Inspect Worker startup performance with Wrangler

wrangler check startup now reports your Worker's raw and compressed bundle sizes. It also summarizes local CPU activity during startup directly in your terminal.

Large bundles and costly startup work can introduce cold-start latency, so use this command to find code and large dependencies that slow your Worker before it handles requests.

The summary includes sampled, active, garbage collection, and idle time. Wrangler continues to save a .cpuprofile file for detailed flamegraph analysis in Chrome DevTools or VS Code.

⛅️ wrangler 4.116.0
───────────────────────────────────────────────
├ Building your Worker
│ Worker Built! 🎉
│
├ Analysing
│ Startup phase analysed
│
│ Bundle: 7171.25 KiB / gzip: 2197.00 KiB
│
│ Local startup profile:
│   Profile window: 70.3 ms
│   Sampled time: 70.3 ms
│   Active: 38.5 ms (including 3.7 ms garbage collection)
│   Idle: 31.8 ms
│   Samples: 36
│
│ CPU Profile has been written to worker-startup.cpuprofile. Load it into the Chrome DevTools profiler (or directly in VSCode) to view a flamegraph.
│
│ Note that the CPU Profile was measured on your Worker running locally on your machine, which has a different CPU than when your Worker runs on Cloudflare.
│
│ As such, CPU Profile can be used to understand where time is spent at startup, but the overall startup time in the profile should not be expected to exactly match what your Worker's startup time will be when deploying to Cloudflare.

The profile runs locally, so its duration will differ from startup time on Cloudflare. For authoritative startup time, deploy your Worker or upload a version.

Available in Wrangler version 4.116.0 or later. For more information, refer to wrangler check startup.

Filter Durable Object logs and traces by instance ID

Workers Logs and OpenTelemetry spans for Durable Object requests include the Durable Object instance ID.

Use $workers.durableObjectId to filter logs for a specific instance. Root and child spans include the same ID in cloudflare.durable_object.id.

Query Builder filtering traces by Durable Object instance ID

Use these fields to isolate a specific instance and correlate its logs and traces.

For more information, refer to Durable Objects metrics and analytics and Workers tracing spans and attributes.

View total SQLite storage for Durable Object namespaces

You can now monitor the total SQLite storage used by a Durable Object namespace over time in the Cloudflare dashboard. The new Total storage chart shows the maximum storage reported during each hour. This helps you identify storage growth, validate data cleanup, and investigate unexpected usage.

The Total storage chart showing a Durable Object namespace growing to 260.1 MB of storage over time. Go to Durable Objects ↗

The chart appears only for SQLite-backed Durable Object namespaces. It does not appear for namespaces that use the legacy key-value storage backend. Viewing storage for individual Durable Objects by ID or name is not supported.

For more information, refer to Metrics and analytics.

New Durable Object namespaces must use the SQLite storage backend

If your account does not already have a key-value (KV) backed Durable Object namespace, you can no longer create new ones. New Durable Object namespaces must use the SQLite storage backend, which has been recommended for all new Durable Objects since it became generally available ↗︎ in 2024.

Create a new class with a new_sqlite_classes migration:

{
  "$schema": "./node_modules/wrangler/config-schema.json",
  "migrations": [
    {
      "tag": "v1",
      "new_sqlite_classes": [
        "MyDurableObject"
      ]
    }
  ]
}
[[migrations]]
tag = "v1"
new_sqlite_classes = ["MyDurableObject"]

SQLite-backed Durable Objects have feature parity with the key-value backend — including the key-value storage API — and additionally support relational SQL queries and point-in-time recovery to restore an object's storage to any point in the past 30 days.

If you attempt to create a new key-value backed namespace (a new_classes migration) on an affected account, the deployment fails with the following error:

Creating new key-value backed Durable Object namespaces is no longer supported on this account. Please create a namespace using a `new_sqlite_classes` migration instead.

This change only affects accounts that are not already using the key-value storage backend. Accounts with at least one existing key-value backed namespace can still create new ones for now, and the Workers Free plan has only ever supported SQLite-backed Durable Objects. It is part of a broader move toward SQLite as the single storage backend for Durable Objects, ahead of a future migration path for existing key-value backed objects.

For more information, refer to Durable Objects migrations.

Declare Durable Object class lifecycle with `exports`

A new declarative exports field in your Wrangler configuration file replaces the imperative migrations array for managing Durable Object class lifecycle. Instead of writing an ordered list of migration steps with unique tags, you declare each Durable Object class your Worker exports and Cloudflare compares that against what's already deployed to determine what Durable Object state needs to be created, renamed, or deleted.

With legacy migrations, renaming ChatRoom to Room requires retaining both tagged steps:

Before — legacy migrationsjsonc
{
	"migrations": [
		{ "tag": "v1", "new_sqlite_classes": ["ChatRoom"] },
		{
			"tag": "v2",
			"renamed_classes": [{ "from": "ChatRoom", "to": "Room" }],
		},
	],
}

With exports, you instead declare Room as the current class and mark ChatRoom as renamed:

After — declarative exportsjsonc
{
	"exports": {
		"ChatRoom": {
			"type": "durable-object",
			"state": "renamed",
			"renamed_to": "Room",
		},
		"Room": { "type": "durable-object", "storage": "sqlite" },
	},
}

Each entry is keyed by class name. The state field carries the lifecycle (created by default — a live class — plus tombstone states deleted, renamed, and transferred, and the expecting-transfer receiving state for cross-Worker transfers).

Key improvements over the legacy migrations array:

  • No migration tags. The current exports map is the source of truth — there is no historical chain of v1, v2, v3 entries to maintain.
  • Structured deployment output. Wrangler reports when it creates, updates, deletes, renames, or transfers Durable Object classes. It also identifies stale configuration entries that are safe to remove. Deployments with no changes or notices do not print this output.
  • Zero-downtime rename and transfer patterns are first-class. Tombstones may coexist with the source class still in code, enabling a three-deploy rename and a four-deploy cross-Worker transfer without runtime errors during the rollout window.
  • Cross-Worker safety. When you delete or rename a class, Cloudflare lists every other Worker in your account whose bindings still reference the namespace, so you can redeploy them before the change goes live.

Existing Workers using the legacy migrations array continue to work unchanged. To move to exports, refer to the migration guide. exports and migrations are mutually exclusive within a single Worker.

For the full reference, refer to Durable Object class exports.

Track memory usage for Workers and Durable Objects in the dashboard

You can now monitor how much memory your Workers and Durable Objects consume across invocations with the new Memory Usage chart in the Workers Metrics tab, broken down by P50, P90, P99, and P999 percentiles.

Memory usage chart showing P50, P90, P99, and P999 percentiles with deployment markers

Memory usage measures the V8 isolate memory at the time of each invocation, subject to the 128 MB per-isolate limit — a single isolate can handle many concurrent requests and shares memory across them.

Use the Memory Usage chart to:

  • Track memory trends — Spot gradual increases that may indicate a memory leak before they cause Exceeded Memory errors.
  • Correlate with deployments — Deployment markers on the chart help you identify whether a new version introduced a memory regression.
  • Right-size your Worker — Understand your baseline memory footprint and how much headroom you have before hitting the 128 MB limit.

For Durable Objects, memory usage reflects the in-memory state an object holds (class properties, caches, active WebSocket connections), which persists across invocations until the object is hibernated or evicted. This state is not preserved across eviction, hibernation, or a crash, so persist anything important to storage.

To view memory usage, open the Metrics tab for your Worker ↗︎ or Durable Object namespace ↗︎. For Durable Objects, you can filter by DO ID or name to drill down into memory usage for a specific object. You can also query memory usage programmatically via the GraphQL Analytics API using the workersInvocationsAdaptive dataset — the quantiles.memoryUsageBytesP50 through quantiles.memoryUsageBytesP999 fields return percentile values in bytes.

For local memory debugging, you can also profile memory with DevTools to take heap snapshots and identify specific objects causing high memory usage.

New `us` jurisdiction for Durable Objects

Durable Objects now supports a us jurisdiction, letting you create Durable Objects that only run and store data within the United States. Use the us jurisdiction when you need to keep a Durable Object's compute and storage inside the United States to meet data residency requirements.

Create a namespace restricted to the us jurisdiction the same way as any other jurisdiction:

// Worker
export default {
	async fetch(request, env) {
		const usSubnamespace = env.MY_DURABLE_OBJECT.jurisdiction("us");
		const stub = usSubnamespace.getByName("general");
		return stub.fetch(request);
	},
};

Workers may still access Durable Objects constrained to the us jurisdiction from anywhere in the world. The jurisdiction constraint only controls where the Durable Object itself runs and persists data.

For the full list of supported jurisdictions, refer to Data location — Restrict Durable Objects to a jurisdiction.

Test Durable Object eviction with new cloudflare:test helpers

The @cloudflare/vitest-pool-workers package now includes evictDurableObject and evictAllDurableObjects test helpers, exported from cloudflare:test.

These helpers let you test how a Durable Object behaves across evictions, simulating the production lifecycle where an idle Durable Object can be evicted from memory.

For more context, refer to Lifecycle of a Durable Object.

import { evictDurableObject, evictAllDurableObjects } from "cloudflare:test";
import { env } from "cloudflare:workers";

const id = env.COUNTER.idFromName("my-counter");
const stub = env.COUNTER.get(id);

// Evict the Durable Object instance pointed to by a specific stub
await evictDurableObject(stub);

// Close WebSockets instead of hibernating them
await evictDurableObject(stub, { webSockets: "close" });

// Evict all currently-running Durable Objects in evictable namespaces
await evictAllDurableObjects();

These helpers are available in @cloudflare/vitest-pool-workers@0.16.20 and later.

Learn more in the Test APIs reference and the Testing Durable Objects guide.

New Asia-Pacific location hints: apac-ne and apac-se

Durable Objects now supports two new location hints for Asia-Pacific: apac-ne (Northeast Asia-Pacific) and apac-se (Southeast Asia-Pacific). Use apac-ne or apac-se when you want finer-grained placement within Asia-Pacific rather than the broader apac hint.

Use the new hints the same way as any other locationHint:

// Northeast Asia-Pacific (Japan, Korea, etc.)
const stubNE = env.MY_DURABLE_OBJECT.get(id, { locationHint: "apac-ne" });

// Southeast Asia-Pacific (Singapore, Indonesia, etc.)
const stubSE = env.MY_DURABLE_OBJECT.get(id, { locationHint: "apac-se" });

If your users are spread across all of Asia-Pacific, the existing apac hint remains the right choice. Only reach for apac-ne or apac-se when your traffic is clearly concentrated in one sub-region and you want to minimize round-trip time to that audience. The default behavior and what we generally recommended is not adding a location hint unless absolutely needed, this will create the Durable Object as close to the initializing request as possible to reduce latency.

As with all location hints, these are best-effort suggestions. Cloudflare will place the Durable Object in a nearby data center, not necessarily the exact hinted location.

For the full list of supported hints, refer to Data location — Provide a location hint.

Outbound connections keep Durable Objects alive

Durable Objects now remain alive for the duration of active outbound connections created via connect() or an outbound WebSocket. Previously, a Durable Object would be evicted after 70-140 seconds of no incoming traffic, even if the object had an open outbound connection, which is a common pattern when streaming responses from a large language model (LLM) over TCP or an outbound WebSocket.

With this change, each active outbound connection prevents eviction. Once all outbound connections close, the standard 70-140 second inactivity window applies before the Durable Object is evicted.

Before: streaming connections were cut off by eviction

Timeline showing a Durable Object evicted 70-140 seconds after the last incoming request, cutting off an in-flight LLM stream while the outbound connection is still open

After: active outbound connections keep the Durable Object alive

Timeline showing the same outbound stream completing because the active connection keeps the Durable Object alive, with the inactivity window starting only after the connection closes

If you are building agents on Cloudflare, this is especially relevant. An agent that streams tokens from an LLM while calling models, or that performs long-running tasks over an outbound connection, now stays alive for the duration of that connection instead of being evicted mid-stream.

Limits:

  • Each outbound connection keeps the Durable Object alive for a maximum of 15 minutes. After 15 minutes, the connection stops preventing eviction (the connection itself continues operating), and the standard eviction rules resume.
  • The Durable Object's existing per-account instance limits still apply.

For more information, refer to Lifecycle of a Durable Object.

Filter Durable Objects metrics by object ID or name

You can now filter the Metrics tab for a Durable Objects namespace by an individual Durable Object's ID or name in the Cloudflare dashboard. Previously, metrics charts only showed aggregate, namespace-level data, making it difficult to isolate the behavior of a specific object.

Go to Durable Objects ↗ The Durable Objects Metrics tab filtered to a single object by ID, showing per-object requests and errors by invocation status.

Start typing an ID or name into the filter and select a match from the autocomplete dropdown. The autocomplete only shows objects with invocations during the selected time range, so an object that does not appear has not been invoked in that window. This does not necessarily mean the object has been deleted. Every chart on the page updates to reflect only the selected object. This makes it easier to identify and investigate a single Durable Object when debugging a high-traffic object, an error spike, or unexpected storage usage. Clear the filter to return to namespace-level metrics.

Metrics are powered by the GraphQL Analytics API, so standard analytics behavior such as ingestion delay and sampling applies.

For more information, refer to Metrics and analytics.

Billable usage and budget alerts now in product sidebars

Pay-as-you-go customers can now view billable usage and create budget alerts directly from the product overview pages for Workers & Pages, D1, R2, Workers KV, Queues, Vectorize, Durable Objects, and Containers. A new sidebar widget shows current-period spend and the billing cycle date range, alongside a button to create a budget alert.

The widget pulls from the same data as the Billable Usage dashboard and aligns to your billing cycle (or the current day on Free plans), so the numbers match your invoice. Enterprise contract accounts are not yet supported.

Billable usage widget in the Durable Objects product sidebar showing current-period spend and a breakdown by service

Selecting Create budget alert opens the budget alert flow inline so you can set a dollar threshold in the same place you are reviewing usage. Budget alerts apply to your total account-level spend across all products, not just the product page you create them from.

For more information, refer to the Usage-based billing documentation.

Access Durable Object jurisdiction via `ctx.id.jurisdiction`

ctx.id.jurisdiction inside a Durable Object now reports the jurisdiction the object was created in — for example "eu" when accessed through env.MY_DURABLE_OBJECT.jurisdiction("eu") — so you can make region-aware decisions without passing the jurisdiction through method arguments or persisting it in storage. For the full list of ID-construction paths that preserve jurisdiction, refer to the Durable Object ID documentation.

export class RegionalRoom extends DurableObject {
	async fetch(request) {
		// "eu" when accessed through env.MY_DURABLE_OBJECT.jurisdiction("eu")
		const region = this.ctx.id.jurisdiction;
		return new Response(`Hello from ${region ?? "the default region"}!`);
	}
}

// Worker
export default {
	async fetch(request, env) {
		const stub = env.MY_DURABLE_OBJECT.jurisdiction("eu").getByName("general");
		return stub.fetch(request);
	},
};

ctx.id.jurisdiction is undefined for Durable Objects that were not created in a jurisdiction-restricted namespace. Alarms scheduled before 2026-03-15 also do not have jurisdiction stored; to backfill the value, reschedule the alarm from a fetch() or RPC handler.

Access Durable Object name via `ctx.id.name`

When your Worker accesses a Durable Object via idFromName() or getByName(), the same name is now available on ctx.id.name inside the object — no need to pass it through method arguments or persist it in storage. This brings the runtime behavior in line with the Workers runtime types.

This is especially useful for alarms, where there is no calling client to pass the name as an argument. When an alarm handler runs, ctx.id.name will hold the same name the object was originally accessed with.

import { DurableObject } from "cloudflare:workers";

export class ChatRoom extends DurableObject {
  async getRoomName() {
    // ctx.id.name returns the name passed to getByName() or idFromName()
    return this.ctx.id.name;
  }
}

// Worker
export default {
  async fetch(request, env) {
    const stub = env.CHAT_ROOM.getByName("general");
    const roomName = await stub.getRoomName();
    return new Response(`Welcome to ${roomName}!`);
  },
};

ctx.id.name is undefined in the following cases:

  • For Durable Objects created with newUniqueId().
  • When accessed via idFromString(), even if the ID was originally created from a name.
  • For names longer than 1,024 bytes.

This works the same way in local development with wrangler dev as it does in production. Run npm update wrangler to ensure you are on a version with this support.

For more information, refer to the Durable Object ID documentation.

deleteAll() now deletes Durable Object alarm

deleteAll() now deletes a Durable Object alarm in addition to stored data for Workers with a compatibility date of 2026-02-24 or later. This change simplifies clearing a Durable Object's storage with a single API call.

Previously, deleteAll() only deleted user-stored data for an object. Alarm usage stores metadata in an object's storage, which required a separate deleteAlarm() call to fully clean up all storage for an object. The deleteAll() change applies to both KV-backed and SQLite-backed Durable Objects.

// Before: two API calls required to clear all storage
await this.ctx.storage.deleteAlarm();
await this.ctx.storage.deleteAll();

// Now: a single call clears both data and the alarm
await this.ctx.storage.deleteAll();

For more information, refer to the Storage API documentation.

New Best Practices guide for Durable Objects

A new Rules of Durable Objects guide is now available, providing opinionated best practices for building effective Durable Objects applications. This guide covers design patterns, storage strategies, concurrency, and common anti-patterns to avoid.

Key guidance includes:

  • Design around your "atom" of coordination — Create one Durable Object per logical unit (chat room, game session, user) instead of a global singleton that becomes a bottleneck.
  • Use SQLite storage with RPC methods — SQLite-backed Durable Objects with typed RPC methods provide the best developer experience and performance.
  • Understand input and output gates — Learn how Cloudflare's runtime prevents data races by default, how write coalescing works, and when to use blockConcurrencyWhile().
  • Leverage Hibernatable WebSockets — Reduce costs for real-time applications by allowing Durable Objects to sleep while maintaining WebSocket connections.

The testing documentation has also been updated with modern patterns using @cloudflare/vitest-pool-workers, including examples for testing SQLite storage, alarms, and direct instance access:

test/counter.test.jsjs
import { env, runDurableObjectAlarm } from "cloudflare:test";
import { it, expect } from "vitest";

it("can test Durable Objects with isolated storage", async () => {
	const stub = env.COUNTER.getByName("test");

	// Call RPC methods directly on the stub
	await stub.increment();
	expect(await stub.getCount()).toBe(1);

	// Trigger alarms immediately without waiting
	await runDurableObjectAlarm(stub);
});
test/counter.test.tsts
import { env, runDurableObjectAlarm } from "cloudflare:test";
import { it, expect } from "vitest";

it("can test Durable Objects with isolated storage", async () => {
	const stub = env.COUNTER.getByName("test");

	// Call RPC methods directly on the stub
	await stub.increment();
	expect(await stub.getCount()).toBe(1);

	// Trigger alarms immediately without waiting
	await runDurableObjectAlarm(stub);
});

Billing for SQLite Storage

Storage billing for SQLite-backed Durable Objects will be enabled in January 2026, with a target date of January 7, 2026 (no earlier).

To view your SQLite storage usage, go to the Durable Objects page

Go to Durable Objects ↗

If you do not want to incur costs, please take action such as optimizing queries or deleting unnecessary stored data in order to reduce your SQLite storage usage ahead of the January 7th target. Only usage on and after the billing target date will incur charges.

Developers on the Workers Paid plan with Durable Object's SQLite storage usage beyond included limits will incur charges according to SQLite storage pricing announced in September 2024 with the public beta ↗︎. Developers on the Workers Free plan will not be charged.

Compute billing for SQLite-backed Durable Objects has been enabled since the initial public beta. SQLite-backed Durable Objects currently incur charges for requests and duration, and no changes are being made to compute billing.

For more information about SQLite storage pricing and limits, refer to the Durable Objects pricing documentation.

View and edit Durable Object data in UI with Data Studio (Beta)

Screenshot of Durable Objects Data Studio

You can now view and write to each Durable Object's storage using a UI editor on the Cloudflare dashboard. Only Durable Objects using SQLite storage can use Data Studio.

Go to Durable Objects ↗

Data Studio unlocks easier data access with Durable Objects for prototyping application data models to debugging production storage usage. Before, querying your Durable Objects data required deploying a Worker.

To access a Durable Object, you can provide an object's unique name or ID generated by Cloudflare. Data Studio requires you to have at least the Workers Platform Admin role, and all queries are captured with audit logging for your security and compliance needs. Queries executed by Data Studio send requests to your remote, deployed objects and incur normal usage billing.

To learn more, visit the Data Studio documentation. If you have feedback or suggestions for the new Data Studio, please share your experience on Discord ↗︎