Architecture

Why I Always Start With the Database Schema

March 15, 20266 min readBy Belmond Joe Candelaria

"A schema designed for today will betray you at scale. Design for the third version of the feature."

The schema is not a detail — it is the contract

Every application I have rescued from technical debt shared one origin story: someone rushed past the data model to ship a screen. The UI looked fine on day one. Six months later, every new feature required a migration, a workaround, or a full rewrite of a service layer that was never designed to bend.

I treat the database schema as the first deliverable, not the last. Before a single React component or Laravel controller exists, I want to answer three questions:

  • What entities exist in this system, and how do they relate?
  • What invariants must never be violated (even under bad input or race conditions)?
  • What queries will this product need in 12 months, not just at launch?

If you cannot answer those on paper, you are not ready to write production code.

Design for the third version of the feature

Clients rarely ask for complexity on day one. They ask for a simple CRUD form. Then they want approvals. Then audit logs. Then multi-branch access. Then reporting across fiscal years.

A schema designed only for version one collapses under version three. That is why I model the relationships I *expect* before they are requested:

  • Soft deletes when history matters (HR, finance, healthcare)
  • Tenant or org identifiers when a second client is even remotely possible
  • Status enums as lookup tables, not magic strings scattered through PHP and JavaScript
  • Timestamps on everything that could end up in a compliance conversation

This is not over-engineering. It is buying optionality at the cheapest point in the project lifecycle.

A real example: HRMS payroll

On a human resource management system for a construction company, the first requirement was straightforward — store employee records and generate payslips. The temptation was a flat employees table with salary columns and a PDF export.

Instead, we modeled:

  • employees linked to departments and positions
  • payroll_runs as first-class records (not just generated files)
  • attendance_logs with source metadata (manual, biometric, imported)
  • leave_requests with approval chains

When the client asked for leave accrual rules and retroactive adjustments three months later, we added columns and indexes — we did not restructure the entire application. The schema had room to grow because we designed for payroll as a *process*, not a print button.

Signs your schema is already fighting you

If any of these sound familiar, the data model needs attention before more UI work:

  1. **JSON blobs** storing data you query or filter on regularly
  2. **Polymorphic associations** added without a clear ownership model
  3. **Duplicate tables** for "archived" records because deletes were never planned
  4. **N+1 queries** that can only be fixed with caching, not better structure
  5. **Migrations** that require downtime because a column was an afterthought

My practical workflow

  1. **Interview stakeholders** for nouns and verbs — what *things* exist, what *happens* to them
  2. **Draw an ERD** (even a rough one) and walk through three realistic user stories
  3. **Write the migration** with foreign keys, indexes on filter columns, and explicit constraints
  4. **Seed realistic data** — not "Test User 1" — and run the queries the dashboard will need
  5. **Only then** scaffold API routes and UI components

Laravel makes step 4 fast. React makes step 5 pleasant. Neither saves you from a schema that lies about how the business actually works.

Closing thought

The frontend gets the applause. The schema does the heavy lifting. When I start with the database, every layer above it — APIs, validation, UI states, reports — inherits a clear vocabulary. That is not slower development. It is development that still makes sense a year from now.

If you are starting a new product and feel pressure to skip straight to screens, pause. Open a blank diagram. Name your tables. Your future self — and your client — will thank you.

© 2026 Belmond Joe Candelaria

"I build systems that feel alive"