A customer record has invoices, notes and uploaded files. The interface offers one button: Delete. Before writing the handler, the team needs to decide which of those objects should disappear, remain or lose their association.
List the relationships
Draw the parent record and its related data. Separate records owned entirely by that parent from shared resources and records with independent retention requirements. A file referenced by several accounts is not equivalent to a private draft note.
In PostgreSQL’s constraint documentation, foreign-key actions include options such as restricting deletion, cascading it or setting a reference to null. These are mechanisms for enforcing a decision. They do not decide the product’s retention policy for you.
Write the behaviour as examples
- A record with no dependants can be removed under the approved policy.
- A record with retained invoices needs the defined handling for those invoices.
- A shared attachment remains available to its other authorised owners.
- A failed operation leaves a state the system can explain and recover from.
These are example categories, not universal rules. Agree the actual policy with the responsible product, privacy and legal stakeholders where needed. Explain whether “delete” means immediate removal, a reversible holding period or another approved process.
Test the awkward cases in a disposable environment
Include multiple related rows, shared files, concurrent requests and a repeated delete attempt. Verify authorisation for both the requested record and the effects on related data. Check transaction boundaries and any separate background cleanup.
The confirmation message should describe the meaningful consequence, not expose database jargon. After completion, the interface should accurately state what happened and any remaining steps.
Finally, test the recovery procedure appropriate to the design. A backup existing somewhere is not the same as a practical way to restore one mistaken deletion.
A reliable delete feature begins with a clear data-lifecycle decision. The button is the visible end of that decision, not the place where it should first be discovered.

