← Back to Blog
March 6, 2026 postgresql 2 min read

Anti-Pattern: Writing Code Before the Schema is Locked

When database changes break the API weekly, your project is bleeding out. Lock the database schema first, define the API contracts second.

anti-pattern schema architecture database

The "Anti-Patterns I Eliminate" Series

Most software development doesn't fail because of difficult technical problems. It fails because of unforced structural errors. In this series, I break down the architectural anti-patterns that bleed agency margins and how I architect systems to eliminate them entirely.

Failure pattern #1 is the deadliest: Writing application code before the database schema is locked.

We have all seen this. A client approves a design. The frontend team immediately starts building React components. The backend team starts spinning up Express routes. And nobody actually wrote down how the data relates to itself. You are building a house without pouring the foundation.

// Key Takeaway

The database outlives the codebase. Frontends get rewritten every 3 years. APIs change. The data is forever. Respect the data model.

The Root Cause: Dopamine Development

Developers rush to build features because shipping code feels productive. Defining schemas and writing API contracts feels bureaucratic. But when you build an endpoint to fetch a User object without realizing that a User can belong to multiple Companies, your initial API design is fundamentally flawed.

[Image of database schema ERD]

You don't discover this flaw until Week 4 when the frontend tries to render the "Switch Company" dropdown. Now, everything halts.

The Ripple Effect of Schema Changes

Let's trace the cost of a missing relational column discovered mid-sprint:

  • The Database: You must write a migration to alter the table, assign default values, and ensure existing data isn't corrupted.
  • The Backend: You have to rewrite the SQL joins, update the ORM models, and refactor the API response payload.
  • The Frontend: The UI now receives a different JSON structure. Typescript throws 50 errors. The component tree must be updated to handle the new state.

A 10-minute whiteboard discussion in Week 0 just cost you 3 days of billable developer time in Week 4.

The Fix: Strict API Contracts

I do not allow a single line of frontend or backend code to be written until the database schema (ERD) is approved and the API contract is written.

By defining the PostgreSQL schema first, we know exactly what is possible. We then map those possibilities to strict OpenAPI specifications (Swagger). The backend team knows exactly what JSON shape they must deliver. The frontend team knows exactly what JSON shape they will receive.

-- The foundation must be rigid so the application can be flexible
CREATE TABLE companies (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    name TEXT NOT NULL
);

CREATE TABLE users (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    email TEXT UNIQUE NOT NULL
);

-- The relationship is locked before code is written
CREATE TABLE company_users (
    company_id UUID REFERENCES companies(id),
    user_id UUID REFERENCES users(id),
    role TEXT NOT NULL,
    PRIMARY KEY (company_id, user_id)
);

Eliminate the Variables

When you lock the schema and the contract first, you eliminate 80% of QA bugs. You aren't debugging data shape issues or missing foreign keys; you are only debugging pure business logic. Stop coding in the dark. Plan the data, then write the code.

Start Your Moat Audit ← Back to all posts

// Related Posts

Mar 16, 2026

PostgreSQL: The Only Database You Actually Need

You do not need MongoDB for documents or Pinecone for AI. Postgres JSONB and pgvector handle it all without sacrificing relational integrity.

Mar 15, 2026

PostgreSQL: When to Use JSONB vs Relational Columns

The definitive guide to choosing between JSONB flexibility and relational structure in PostgreSQL.

Mar 16, 2026

Zero-Downtime Migrations: Keeping the Engine Running

If updating your schema forces you to put up a "maintenance mode" banner, your deployment strategy is obsolete. Here is how to orchestrate seamless updates.

← PreviousThe 3-Second Bounce: Why Harris County Roofing Traffic Dies on Arrival (The 14-Day Fix That Books Jobs)Next →Deploy Private LLMs on Your Own Hardware