The fastest code I've ever written is code that queries a well-designed schema. The slowest is code that fights a bad one. Most of a backend's long-term health is decided at the schema, before a single endpoint exists.
I design schemas for systems where configuration is the whole point — device settings, workflow definitions, role assignments. They get edited constantly and read even more. A few principles have earned their keep.
Model the relationships, not the screens
It's tempting to shape tables around the UI you're building this sprint. Don't. The UI will change three times; the relationships between a site, its equipment, and that equipment's configuration won't. Model the domain and let the screens query it.
Make illegal states unrepresentable
Every constraint you push into the database is a class of bug your application code never has to handle. Foreign keys, unique constraints, NOT NULL, enums — they're not bureaucracy, they're free validation that can't be bypassed by the next service that talks to the table.
Plan for audit from day one
On the systems I work on, "what changed, when, and who did it" is a requirement, not a nice-to-have. Retrofitting history onto a schema that wasn't designed for it is miserable. Decide early whether a table is append-only, soft-deleted, or fully versioned — and be consistent.
Indexes are a conversation with your query patterns
Add them deliberately, based on how you actually read the data, and revisit them when access patterns shift. An index you never query is just write-time tax.
A schema is a promise about what will stay true. The good ones keep that promise long after you've forgotten you made it.