Use native Durable Objects when one Worker needs named, stateful coordination with SQLite storage, alarms, RPC, or WebSockets. Deploy them through Wrangler in the same project as their owning Worker; no platform-specific deployment command or Ansible application role is involved.
Deploy a namespace
Declare the binding and migration in wrangler.jsonc:
{
"name": "durable-counter",
"main": "src/index.js",
"compatibility_date": "2026-09-30",
"durable_objects": {
"bindings": [{ "name": "COUNTERS", "class_name": "Counter" }]
},
"migrations": [
{ "tag": "v1", "new_sqlite_classes": ["Counter"] }
]
}Export Counter from the Worker module and deploy normally with wrangler deploy. Wrangler reads the active migration tag from the control plane, uploads
the next immutable Worker version, and submits the required namespace migration.
The platform validates the complete native workerd configuration before making
that version active.
The current migration surface supports new_sqlite_classes and
renamed_classes. Namespace deletion, class transfer, legacy key-value-backed
classes, and cross-Worker namespace bindings are rejected explicitly. Use a
same-organization service binding when another Worker needs to call the owning
Worker.
Runtime behavior
Stateful Workers use unmodified workerd Durable Object namespaces with SQLite enabled. Native object addressing, RPC, transactional storage, SQL, alarms, and WebSockets execute inside workerd. The platform does not emulate the namespace API or intercept object methods.
The default fleet declares two fixed shared shard members on data-02. Each
member is one systemd-managed workerd process that can host many stateful Worker
applications and object instances. An application receives a stable,
host-qualified shard assignment such as data-02-0; adding a member on either
data node expands placement capacity without remapping existing applications.
There is never one process, VM, or systemd unit per Worker or object.
Object state is stored beneath /var/lib/ermahgerd-durable on the assigned data
node. Assignments are not replicated, automatically failed over, or
automatically migrated. Removing or moving an occupied shard therefore requires
an explicit state migration. The local fleet remains single-region and non-HA.
The same native shard substrate also hosts platform-owned Cron coordinator objects. There is one coordinator object per organization on a stable shard; its SQLite state, alarm, delivery lease, suspension state, and retry schedule replace the former control-plane polling loop. This reuse is deliberately below the service-semantics boundary: application Durable Objects and Cron retain separate schemas and APIs.
Queues already use workerd Durable Objects for their broker state, alarms, leases, retries, retention, and dead-letter transitions. That proven queue state machine remains owned by the queue service and currently runs in its dedicated workerd service. It is not reimplemented through the application namespace API or collapsed into a generic coordinator object.
Deployments and operations
A code update preserves namespace identities and their SQLite files. Applying a namespace migration is an optimistic transition from Wrangler’s observed migration tag. The shard manager encrypts staged application bundles, records cutover intent in SQLite, validates the candidate configuration, and restores the last committed configuration after an interrupted or failed cutover.
Workerd owns each SQLite namespace through one process at a time, so the current implementation performs a stop-before-start shard cutover. Applications sharing that member can see a brief interruption during an update; the platform does not claim zero-downtime Durable Object deployments yet. Lifecycle events and cutover duration are recorded for the Worker.
In the tenant console, open Compute → Durable Objects to browse all of your organization’s application namespaces. Filter by class or owning Worker, then open a namespace to inspect its identity, assigned member, migration tag, stored object databases, and storage usage. Lifecycle shows paginated deployment and recovery events for the owning Worker. Filters and page selections are bookmarkable. The owning Worker’s Durable Objects tab links to the same namespace detail.
Stored object counts describe persisted databases, not running instances. The inventory excludes the platform’s internal Cron and queue coordination objects. Class definitions and migrations remain in Wrangler; there is no console action to delete a namespace or move its state between hosts.
Platform operators see shard process health and resource pressure with the rest of the selected data host in Platform → Fleet.
Namespace holdings are enforced through the quota service before growth. A Free organization starts with three namespaces, Standard with 20, and Enterprise with 100 unless an explicit support override applies. Reducing a limit does not delete state; it prevents further namespace growth while usage remains over the limit.
Run the example
The durable counter example demonstrates named
objects, native RPC, SQL persistence, an alarm, and a WebSocket endpoint. It is
deployed and verified by make examples-deploy and exercised again by make examples-test.