Recycle bin
Deleting a datasource or a data asset in Measured Cloud does not destroy it. The object — and everything Measured Cloud owns underneath it — is moved to the recycle bin: soft-deleted, hidden from every normal list and query, but recoverable. Items sit in the bin for RECYCLE_BIN_RETENTION_DAYS (30 by default), after which a daily cron purges them for good. Until then you can restore an item back to exactly where it was, or purge it early.
This replaces the older hard-delete-blocked-by-a-guard behaviour (#722): a datasource with assets, or an asset included in a validation, used to return 409 Conflict and refuse to delete. Now the delete always succeeds as a reversible move to the bin.
What gets binned, what is kept
A delete tombstones only the owned subtree of the thing you deleted — the resources that exist solely because that datasource or asset exists — under a single deletion_group_id. Restore clears that group; purge destroys it. The whole group is treated as one unit, so restoring a binned datasource also brings back its assets.
Binned (hidden, purged after the window):
| Delete a… | …and these are binned with it |
|---|---|
| Datasource | the datasource, all of its data assets, and each asset's rules |
| Data asset | the asset and its rules |
Kept, never touched by a delete:
- Validations — a validation that includes a binned asset drops it while it's binned: the asset leaves the validation's Assets list and its asset count, and runs skip its rules. A restore puts it back exactly as it was (its rules are binned with the same
deletion_group_id, and the validation's membership rows are never changed). A permanent purge removes the asset's membership rows along with its rules. The validation itself is a shared object and survives. - Validation results and execution runs — the historical run record is immutable and is never deleted, even on a permanent purge. A purged asset's past results stay, detached from it.
- Agent tokens — untouched.
The distinction is ownership: the recycle bin only ever bins the resources that belong exclusively to the thing you deleted. Anything shared stays live.
The retention window
While an item is in the bin:
- It is invisible everywhere a live object would appear — datasource / asset lists, search, and validation runs. A database-session filter (
deleted_at IS NULL) hides binned rows from every read path automatically, so nothing surfaces a tombstoned object by accident. - Its
purge_atisdeleted_at + RECYCLE_BIN_RETENTION_DAYS. The recycle-bin list shows both timestamps so you can see how long you have. - A daily worker cron (03:45 UTC) hard-deletes every item whose window has elapsed. Purge reuses the same cascade a manual purge does — it destroys the owned subtree and leaves shared objects (validations, results, agent tokens) intact.
Lower RECYCLE_BIN_RETENTION_DAYS for a shorter safety net or raise it to keep deleted objects recoverable longer — see reference/configuration.md.
Operations you can do
The bin is exposed at /api/v2/organizations/{org_id}[/workspaces/{ws_id}]/recycle-bin. Every route is workspace-isolated — you only ever see and act on items in workspaces you can reach.
- List the bin —
GET .../recycle-binreturns the top-level restorable entries: every binned datasource, plus assets that were binned on their own (their parent datasource is still live). An asset binned as part of a datasource delete is covered by the datasource's entry, not listed separately. Each entry carriesresource_type,id,name,deleted_at,purge_at, anddeletion_group_id. - Preview a delete's blast radius —
GET .../recycle-bin/preview/datasource/{id}(or.../preview/data-asset/{id}) counts what a delete would bin (assets and their rules, profile runs, anomaly events, AI suggestions) and how many validations it would leave in place (rule_groups_kept), plus theretention_days. The full count keys are listed in the API reference. Use it to warn a user before they delete a large subtree. - Restore —
POST .../recycle-bin/datasources/{id}/restore(or.../data-assets/{id}/restore) clears the tombstone for the wholedeletion_group_id, so the object and its owned subtree reappear where they were. Restoring an asset whose parent datasource is also in the bin returns409and tells you to restore the datasource first. If the asset and datasource were binned in the same delete they share a group, so restoring the datasource brings the asset back with it; if the asset was binned independently and its datasource binned later (separate groups), restoring the datasource clears only its own group and you restore the asset afterward. - Purge (permanent delete) —
DELETE .../recycle-bin/datasources/{id}(or.../data-assets/{id}) hard-deletes a binned item's owned subtree immediately, without waiting for the retention window. Shared objects and validation results are still preserved. This is irreversible.
Who can do what
The recycle bin follows the same authority gradient as the catalog it protects. Deleting a datasource is an editor-tier action, deleting an asset needs a workspace admin, and permanently destroying anything needs a workspace admin or super admin.
| Action | Minimum role |
|---|---|
| Delete a datasource (move to bin) | editor |
| Delete a data asset (move to bin) | workspace admin |
| List the bin / preview / restore | editor |
Permanent purge (DELETE .../recycle-bin/...) | workspace admin |
Restore and purge are audit-logged (a restore / purge audit event naming the object and, for a restore, the per-table restored-row counts). See Restore or permanently delete from the recycle bin for the task walkthrough and the API reference for the endpoint contracts.