Skip to content

Lifecycle: Soft Delete, Restore, Purge

Purpose

The platform must support safe deletion behavior.

Normal users should not accidentally destroy business-critical asset, credential, audit, or relationship history.

Lifecycle States

The baseline lifecycle uses timestamps.

text
Active:      deleted_at IS NULL
Soft-deleted: deleted_at IS NOT NULL
Purged:      physically removed

Future states may add archival or legal hold.

Default Rule

Normal delete means soft delete.

sql
UPDATE entities
SET deleted_at = now(), updated_at = now()
WHERE id = $1;

Hard delete should be explicit and usually performed by a purge job after retention rules are satisfied.

Soft Delete Scope

Soft-deleting an entity should normally affect its subtree.

Example:

text
Customer
├── Site
│   └── Building
│       └── Asset
└── Site

Soft-delete customer should soft-delete:

  • customer entity,
  • descendant entities,
  • relevant domain records,
  • property values,
  • tag assignments,
  • group memberships where appropriate,
  • relationships touching affected entities.

Soft Delete Query

Find affected subtree:

sql
SELECT descendant.id
FROM entities target
JOIN entities descendant ON descendant.path <@ target.path
WHERE target.id = $1
  AND descendant.deleted_at IS NULL;

Soft Delete Transaction

Pseudo flow:

text
begin transaction
  assert user can delete target
  load target subtree ids
  soft-delete relationships touching subtree
  soft-delete tag assignments for subtree
  soft-delete group memberships for subtree
  soft-delete property values for subtree
  soft-delete domain records for subtree
  soft-delete entities in subtree
  write audit events
commit

Restore

Restore reverses soft delete.

Important question:

text
Should restore include all descendants automatically?

Recommended behavior:

  • restore subtree by default when the original delete was subtree delete,
  • require parent/root to be active before restoring a child,
  • do not restore records that were independently deleted before the parent delete unless you track delete batches.

Delete Batch ID

For better restore behavior, introduce a delete batch concept later.

Example:

text
deleted_batch_id uuid null

This allows restore to distinguish:

text
Deleted because parent was deleted

from:

text
Deleted independently earlier

Alpha can start without this if restore requirements are simple.

Purge

Purge means physical deletion.

Purge should be rare, explicit, audited, and protected.

Recommended flow:

text
Soft Delete

Retention Period

Purge Eligibility Check

Hard Delete Transaction

Purge Order

Delete leaf/dependent records before entities.

Recommended order:

text
1. audit-safe references or event redaction where required
2. property values
3. tag assignments
4. group memberships
5. relationships
6. domain tables
7. entities
8. type/template metadata only if explicitly purging configuration

Because foreign keys use ON DELETE RESTRICT, purge logic must be deliberate.

Relationships During Delete

When an entity is soft-deleted, active relationships touching it should normally be soft-deleted.

Cases:

text
source in deleted subtree
target in deleted subtree
both in deleted subtree

Default Alpha rule:

text
Soft-delete relationships where source or target is in deleted subtree.

Groups During Delete

If a group is deleted:

  • soft-delete group entity,
  • soft-delete group metadata,
  • soft-delete memberships.

If a member entity is deleted:

  • soft-delete memberships involving that member.

Do not delete other group members.

Tags During Delete

If a tag entity is deleted:

  • soft-delete tag metadata,
  • soft-delete assignments using that tag.

If a tagged entity is deleted:

  • soft-delete assignments for that entity.

Do not delete tag definitions just because an entity using them was deleted.

Properties During Delete

When an entity is deleted:

  • soft-delete its property values.

Do not delete property definitions or property groups unless deleting configuration metadata explicitly.

Audit Events

Deletion should emit audit events.

Examples:

text
entity.deleted
entity.restored
entity.purged
subtree.deleted
subtree.restored

Avoid placing sensitive values in audit payloads.

Common Mistakes

Mistake: Database cascade for business delete

Do not use ON DELETE CASCADE for normal application deletion.

Mistake: Deleting only the selected row

Hierarchy means descendants must be considered.

Mistake: Restoring child under deleted parent

Restoring a child while its parent remains deleted creates confusing UI behavior.

Mistake: Forgetting relationships

Deleted entities should not appear in active graph views through stale relationships.