← Back to writing

Modeling the domain first

Why I reach for the domain model before the framework, the database, or the API.

Connected entity cards forming a small domain model

Every new project offers the same temptation: open the framework docs, scaffold a database, wire up an endpoint, and start moving. I’ve learned to resist that for one more hour and do something less glamorous first — model the domain.

The domain model is just the set of nouns the system actually cares about and the rules that bind them. An order. A bid. A settlement. What states can it be in, what moves it between them, what must always be true. None of that is about Postgres, React, or which cloud it runs on. It’s about the problem.

I start there because the model is the part that’s expensive to get wrong. A framework you can swap. A database you can migrate. But if the core abstractions don’t match how the business actually thinks, every feature after that fights the grain — and the code fills up with special cases that are really just the model leaking.

A few habits that help:

  • Name things the way the people who do the work name them. If the warehouse team says “consignment,” the code says consignment, not shipmentGroupV2.
  • Make illegal states unrepresentable. If an order can’t be both draft and paid, the types shouldn’t allow it. Let the compiler hold the rule so I don’t have to.
  • Keep the model ignorant of the outside world. It shouldn’t know about HTTP, SQL, or JSON. Those wrap around the model, not the other way round.

This isn’t ceremony, and it isn’t about diagrams for their own sake. Most of the “modeling” is a plain text file and a handful of TypeScript types, thrown away and rewritten three times in an afternoon. The point is to think in the shape of the problem before committing to the shape of the solution.

The interesting twist lately is that AI agents are very good at the second half — scaffolding, wiring, boilerplate — which makes the first half matter more, not less. The clearer the model I hand them, the better the code that comes back. Garbage model in, confident garbage out.

So: domain first. Everything else is plumbing.