Postgres Patterns We Reuse Across Client Projects

01Postgres as the Default
Postgres remains our default for transactional products because it is predictable, observable, and well understood. We standardize migration tooling and naming so any engineer can onboard in an afternoon.
“Postgres is boring in the best way. Boring databases let you spend novelty budget on the product.”
We avoid exotic data stores unless the specific use case demands it. For 95% of applications, a properly tuned Postgres instance is more than enough.
02Indexing Strategy
Indexes are not set-and-forget. We capture slow queries in staging, explain plans before shipping, and avoid premature JSONB unless access patterns truly need it.
- Composite indexes for filter + sort patterns that appear together
- Partial indexes for sparse booleans like is_archived = false
- Avoid indexing low-cardinality columns in isolation
- Revisit indexes after every tenfold traffic jump
03Multi-tenant Architecture
Row-level security and tenancy boundaries are designed up front for multi-tenant SaaS. Retrofitting isolation after launch is painful and risky.
- 01tenant_id on every tenant-scoped table — no exceptions
- 02RLS policies tested with integration tests, not hope
- 03Background jobs always set session context before queries
04API Boundaries
API layers never leak raw SQL shapes to clients. DTOs and validation at the edge keep contracts stable while schemas evolve underneath.
“The database is not your public API. The DTO is.”
By decoupling the database schema from the API response, we can optimize queries without breaking mobile apps or public API consumers.