---
title: "Durable Objects"
---

> Documentation Index
> Fetch the complete documentation index at: https://ermahgerd-docs.t-bd7662a5eeb4.workers.ermahgerd.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Durable Objects

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`:

```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](https://github.com/nullbytelabs/ermahgerd/blob/main/examples/durable-counter) 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`.

Source: https://ermahgerd-docs.t-bd7662a5eeb4.workers.ermahgerd.io/durable-objects/index.mdx
