Database Constraints Are Part of Your Application Logic
Validation in application code is useful, but the database should still protect invariants that must always be true.
The starting point
It is tempting to treat the database as a passive storage layer and put all correctness rules in TypeScript. That works until another code path writes to the same database. Admin actions, background jobs, migrations, scripts, and future services can all bypass assumptions that existed in one application function. Constraints provide a lower boundary where important invariants can be enforced regardless of which application path performs the write.
Application validation and database constraints do different jobs
Application validation gives users useful feedback before a write happens. A database constraint gives the system a final guarantee. A unique slug, a non-null category, or a foreign key relationship should not depend solely on a particular request handler remembering to check it.
The two layers complement each other. Application validation can explain what is wrong. Database constraints ensure that invalid state does not become durable even when another code path makes a mistake.
Constraints make assumptions executable
A schema becomes much more valuable when its important assumptions are encoded. Instead of documenting that an article must have a category and hoping every developer remembers it, the foreign key can enforce the relationship. Instead of hoping slugs remain unique, the unique constraint can enforce it.
This is one reason database design is application design. The schema does not merely describe where bytes go. It defines which states the system is willing to store.


OPEN
Thoughts on the article.