Summary
Please add a supported way to delete one cell so its pre-delete state can never be restored and celld-managed bucket objects containing that state are eventually reclaimed.
This is about one cell / Durable Object instance. Class deletion (deleted_classes) is a related compatibility gap, but it can be handled separately.
Use case
We run one cell per agent session. A user-facing session deletion must remove the product record immediately and must eventually remove the durable session history. Application-level encryption plus key destruction can make retained bytes unreadable, but it does not reclaim storage and should not be the only lifecycle mechanism.
storage.deleteAll() gives the application an empty current database, but celld retains the cell identity and its replicated history. A future restore reads the full LTX lineage from transaction zero and replays the deletion; pre-delete bytes remain in the fleet bucket.
Current v0.4.0 behavior
celld cell list is the only cell command. There is no cell delete/purge command or operator route.
- No code path purges all objects under
cells/<scope>/ (own.json or ltx/...). Eviction removes local SQLite files but retains bucket state.
- Ownership release rewrites
own.json as unowned with a conditional CAS; it does not record that the scope was deleted.
- Recent rows can exist in shared multi-cell bundles at
log/<session>/bundle/.... Recovery folds rows from those bundles back into per-cell LTX prefixes, so deleting only cells/<scope>/ can be undone by later recovery.
- Alarms and placement have separate references under
wake/... and node-cells/...; out-of-line KV values use kv/blobs-v2/<cell>/....
deleted_classes is explicitly rejected with: “Class rename, delete, transfer, and non-SQLite migration semantics need an explicit persisted-state contract before deployment” (deploy validation).
The only related existing issue I found is #168, which fixed storage.deleteAll() dropping Litestream control tables. It does not provide history deletion or storage reclamation.
Required observable contract
After deletion completes:
- activating the same scope cannot restore pre-delete data;
- stale owners, followers, dead-node recovery, and bundle drains cannot reintroduce pre-delete rows;
- alarm and placement references for the cell are gone;
- celld-managed current bucket objects that contain the cell's data are eventually deleted or compacted away, subject to the object store's own versioning/backup policy;
celld cell list no longer returns the cell until a new activation creates empty state;
- repeated delete requests are safe and report whether deletion is pending or complete.
The operation may be asynchronous because a shared bundle can contain rows from several cells. It can remain pending until those rows are covered per-cell and the bundle reaches normal GC.
Possible shape (not a requirement)
An operator command or HMAC-authenticated route, for example:
celld cell delete <SCOPE>
stop admission and evict the cell
publish a durable deletion tombstone at a newer epoch
drain or cover retained bundle rows
purge the cell LTX prefix, wake entries, placement markers, and KV blobs
make every recovery path skip the tombstoned scope
retain the tombstone until every prior node session is fenced
report deletion complete once the last celld-managed copy is reclaimed
The existing code already has useful pieces: conditional ownership updates, drain barriers that wait for bundle coverage, bundle GC, wake-entry deletion, and dead-node cleanup. The missing part appears to be the persisted cell-deletion contract that composes them safely.
Compatibility precedent
Cloudflare's class lifecycle has an explicit permanent-delete tombstone: deleting a class “removes its namespace and all of its stored data permanently — this is not a soft delete.” This is class-level rather than an exact per-instance API match, but it establishes permanent deletion as part of the Durable Object lifecycle contract:
https://developers.cloudflare.com/durable-objects/reference/durable-objects-migrations/#delete-a-durable-object-class
Summary
Please add a supported way to delete one cell so its pre-delete state can never be restored and celld-managed bucket objects containing that state are eventually reclaimed.
This is about one cell / Durable Object instance. Class deletion (
deleted_classes) is a related compatibility gap, but it can be handled separately.Use case
We run one cell per agent session. A user-facing session deletion must remove the product record immediately and must eventually remove the durable session history. Application-level encryption plus key destruction can make retained bytes unreadable, but it does not reclaim storage and should not be the only lifecycle mechanism.
storage.deleteAll()gives the application an empty current database, but celld retains the cell identity and its replicated history. A future restore reads the full LTX lineage from transaction zero and replays the deletion; pre-delete bytes remain in the fleet bucket.Current v0.4.0 behavior
celld cell listis the only cell command. There is no cell delete/purge command or operator route.cells/<scope>/(own.jsonorltx/...). Eviction removes local SQLite files but retains bucket state.own.jsonas unowned with a conditional CAS; it does not record that the scope was deleted.log/<session>/bundle/.... Recovery folds rows from those bundles back into per-cell LTX prefixes, so deleting onlycells/<scope>/can be undone by later recovery.wake/...andnode-cells/...; out-of-line KV values usekv/blobs-v2/<cell>/....deleted_classesis explicitly rejected with: “Class rename, delete, transfer, and non-SQLite migration semantics need an explicit persisted-state contract before deployment” (deploy validation).The only related existing issue I found is #168, which fixed
storage.deleteAll()dropping Litestream control tables. It does not provide history deletion or storage reclamation.Required observable contract
After deletion completes:
celld cell listno longer returns the cell until a new activation creates empty state;The operation may be asynchronous because a shared bundle can contain rows from several cells. It can remain pending until those rows are covered per-cell and the bundle reaches normal GC.
Possible shape (not a requirement)
An operator command or HMAC-authenticated route, for example:
The existing code already has useful pieces: conditional ownership updates, drain barriers that wait for bundle coverage, bundle GC, wake-entry deletion, and dead-node cleanup. The missing part appears to be the persisted cell-deletion contract that composes them safely.
Compatibility precedent
Cloudflare's class lifecycle has an explicit permanent-delete tombstone: deleting a class “removes its namespace and all of its stored data permanently — this is not a soft delete.” This is class-level rather than an exact per-instance API match, but it establishes permanent deletion as part of the Durable Object lifecycle contract:
https://developers.cloudflare.com/durable-objects/reference/durable-objects-migrations/#delete-a-durable-object-class