Technology

Why the guarantees belong in the database

Application checks answer "did we remember here". That question accumulates with every endpoint you add.

Every platform has rules that must never be broken. A payment cannot be authorized without both signatures. A signed agreement cannot be altered. A financial record cannot be deleted. The interesting engineering question is not what the rules are but where they are enforced.

The default answer is the application: validate in the handler, refuse the request, return an error. It works, it is easy to test, and it is the wrong place for anything that genuinely must never happen.

The accumulation problem

An application check protects the path it sits on. Your platform has one path today. Next quarter it has a second endpoint, a partner import, a data migration, an admin tool, and a scheduled job. Each is a new opportunity to omit the check, and the omission is invisible: the code works, the tests pass, and the guarantee is quietly no longer a guarantee.

This is not hypothetical sloppiness. It is the normal outcome of a codebase growing faster than any individual's memory of its invariants.

Where every path converges

The data store. A constraint or trigger there is not a check callers must remember — it is a property of what the system will accept. It covers the endpoint nobody has written yet, the script written under time pressure, and the integration built by a team that never read your design document.

A rule in the application is a promise you have to keep repeating. A rule in the data is a promise you only have to make once.

A caveat worth stating

Database permissions are not a substitute for this. On most managed database services the application connects as the owner of its own tables, and revoking a privilege does not bind an owner. So the enforcement has to be a constraint or a trigger, not a grant.

The honest costs

  • Constraints in the data are harder to change than code, and changing them requires a migration rather than a deploy.
  • They will occasionally refuse something a person believes should be permitted, and resolving that is a conversation rather than a config change.
  • Error messages surface from a lower layer and need deliberate translation into something a user can act on.

All three are real. They are also the price of a guarantee that holds when nobody is watching, which is the only time a guarantee matters.

The practical version

Ask where a rule is enforced, then ask them to bypass it through a different code path. The answer is more informative than any architecture diagram.

Related

All 20 articles

Ask us for the audit pack.

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.