Build for the person who does not like software
Design for the mistake a real person will make, not the path you will demo.
What happened
The ledger’s users are two directors in a construction business, not operators. The first instinct on any interface is to add a delete button; the first instinct of a nervous user is to avoid touching anything at all in case it breaks.
What changed
Destructive actions became voids, never deletes — the record keeps the mistake and the reason for it. Every schema now starts with the recovery path rather than the happy path, and we design for the error a real person will make rather than the demo.
Most business software is designed by people who are comfortable with software, for a demo audience who are also comfortable with software. The actual users are frequently neither.
When we built a financial ledger for a construction company, the users were two directors who had kept the books on paper for years. They were not going to explore. If an action looked like it might break something irreversibly, they would avoid the feature entirely and go back to paper — which is a total product failure that shows up in no error log.
So the destructive action had to go. Nothing in the system can be deleted. A mistake is voided: the record stays, marked as void, with a reason attached. That is better for the accountant, better for the audit trail, and crucially it means no action in the interface can ever lose anything. Confidence to use the tool comes from knowing you cannot break it.
The same reasoning drove the numbering. Vouchers are issued by the database under a row lock, so two people recording payments at the same moment cannot produce a duplicate or a gap. The user never thinks about it, which is the point — correctness they do not have to maintain.
The general rule we took from it: start the schema with the recovery path. What happens when this is wrong, who notices, and how is it put right? Design that first, and the happy path tends to design itself.