← All posts

Start With the Schema

Before you wireframe a single screen, you need to understand the shape of your data — because the schema is the real design

There's a pattern I see on almost every project that starts with UI mockups: the design looks great, the client loves it, and then we start building — and halfway through, we discover the data model doesn't support what the screens implied. Now we're either hacking the schema to fit a design that was drawn without thinking about data, or we're redesigning screens to fit a model that actually makes sense. Neither is fun.

My default now is to design the schema first. Not the database in full production detail, but the core entities, their relationships, and the constraints that have to be true for the system to work. Then the UI.

Here's why.

A mockup hides its assumptions

When you draw a screen that shows a track with multiple writers attached, you've made a data modeling decision without knowing it. What you drew looks like a list. But is it a list? Or is it a join table with extra fields — contribution type, percentage, PRO number, whether the writer controls the sync rights for this track specifically?

The mockup can't tell you. It looks the same either way. A flat list on a screen is compatible with a dozen different data models, some of which are trivially easy to build and some of which will haunt you for the life of the project.

When I was building Composer Catalog — a platform for professional music composers to manage their track catalog, credits, and publishing rights — the initial instinct was to sketch out what the catalog would look like: a grid of tracks, a detail view, filters. Clean, sensible screens. But before I touched a UI file, I sat down with the domain.

A track has writers. But writers have PRO affiliations, CAE/IPI numbers, different contribution types (music only, lyrics only, both). A track can have multiple publishers, but each publisher relationship is scoped to a specific publishing deal with its own terms, reversion dates, and split percentages. A deal can have multiple publishers with different splits. The publishers themselves are entities that appear across many tracks and many deals.

None of that complexity is visible in a mockup. You can draw a track detail page that shows "Writers" and "Publishers" as two clean sections and feel good about your design. But when you go to build it, you either build a data model that can actually represent the domain — which requires join tables, deal entities, relationship metadata — or you build something simpler that breaks the moment a real composer tries to enter their actual situation.

The schema surfaces these questions before you've written a line of application code.

The cost asymmetry

UI is cheap to change. I mean this literally: updating a component, adjusting a layout, changing how data gets displayed — these are relatively low-cost changes that can happen throughout a project's life without much disruption. The schema is not cheap to change. Once you have data in production, changing a core relationship requires a migration, data cleanup, updates to every query that touches the affected tables, and usually some kind of backfill. The longer you wait, the more expensive it gets.

This asymmetry should inform where you spend your design energy early. Front-load the decisions that are expensive to reverse. Schema decisions are expensive. Pixel decisions are not.

The corollary: a UI mockup is a great tool for communicating with a client or stakeholder, but it's a terrible tool for doing architectural thinking. Use it for what it's good at. Do the architectural thinking somewhere else first.

What schema design actually looks like

I'm not suggesting you write production-ready SQL before you've talked to anyone. What I mean is something more like: write down the nouns in the domain and what they know about each other.

For a music catalog: tracks, writers, musicians, publishers, publishing deals, genres, moods. A track has many writers (through a relationship that carries contribution data). A track has many musicians (through a relationship that carries role and work-for-hire status). A track belongs to a publishing deal; that deal has one or more publishers with percentage splits.

When you write these out, questions immediately emerge that a mockup would never surface. Can a writer appear on multiple tracks? Yes — so the writer entity needs to exist independently of any single track. Can a track be in multiple publishing deals? What happens when a writer is also a musician on the same track — are those the same entity or two different roles? These aren't edge cases. These are core modeling decisions that determine whether the system is accurate or approximate.

Once you've worked through the domain model, a lot of UI decisions become obvious. A track detail view needs a section for writer credits because writers are a distinct entity with their own fields. Publishing deals need their own view because they're complex enough to deserve one. The UI is almost falling out of the schema at that point, rather than being invented from scratch.

When to break this rule

There are genuinely cases where starting with the UI makes sense — mostly when the domain is so unclear that you need to prototype in order to understand it. If you're building something genuinely novel, where no one knows exactly what problem you're solving yet, rough UI sketches are a discovery tool. You're not designing a product; you're figuring out what the product is.

But that's rarer than people think. Most projects involve a domain that already exists — someone does the work manually today, or a competing product does something similar, or there's an industry with established terminology and relationships. In those cases, the domain knowledge is available. The schema is discoverable before you write a line of code. You just have to look.

The other exception is pure frontend work — landing pages, marketing sites, content pages with minimal structured data. There the UI really is the product and the "schema" is trivial. No argument there.

The practical version

Before your next kickoff or design sprint: take an hour, before any wireframes go up, and write out the entities in plain language. What are the things the system needs to track? What does each thing know about itself? What are the relationships between things, and what does each relationship carry?

Share that with the team. You'll have better design conversations. The mockups that come out will be grounded in the actual domain rather than a plausible-looking approximation of it. And when you start building, you'll spend your time on real problems instead of correcting the foundational ones.