Why the guarantees belong in the database
Application checks answer "did we remember here". That question accumulates with every endpoint you add.
Soft delete is usually half-implemented, and the missing half is the one users notice.
If a platform's purpose is to be believed later, it cannot be able to destroy its own history. That principle is widely agreed and inconsistently implemented, because "soft delete" has two halves and most implementations ship one.
The familiar part: instead of removing a row, mark it. A timestamp, the identity of whoever did it, and — this part is usually missing — a mandatory reason. A retirement nobody can explain is nearly as unhelpful as a deletion, and it is the field a person reading the record years later most wants.
The stronger version refuses the destructive operation outright rather than relying on the application to choose the gentle path. If a hard delete is merely discouraged, one code path will eventually take it.
If retired records stay in every list, export, and report, then from the user's point of view nothing was deleted at all. They asked to remove something, the system said yes, and it is still there tomorrow. That is worse than refusing, because it silently teaches people the platform does not do what it says.
So every list, every export, and every report has to exclude retired records by default, while the record itself remains queryable for audit. Enforcing only the write half is the most common way this gets shipped broken.
Enforcing only the write half leaves users staring at records they were told they had removed.
This creates a genuine tension with data-subject deletion expectations, and it deserves a straight answer rather than a clever one. Inside an evidence platform, deletion means retirement with a reason and removal from operational use. Where a regulation requires actual erasure of personal data, that is handled as a scoped redaction of identifying fields, recorded as having happened, rather than as a silent removal of the transaction.
The transaction has to survive because a lender's obligation to prove a disbursement was authorized does not expire when a party asks to be forgotten. Saying so plainly in a contract is better than discovering the conflict during an examination.
Delete something in a trial account, then look for it in every export and report. The read half is where soft delete is usually broken.
Pick a closed project. We will show you the document you would hand a regulator. If it does not answer the question, nothing else matters.