From the Technology track

The data model is destiny

You can refactor code in an afternoon. A wrong core entity outlives three rewrites and quietly decides what your product is allowed to become.

Code is cheap to change and data is not, and the gap between them is bigger than almost anyone plans for.

You can restructure a service in a week. You can change languages over a year. But the structure of your core entities, the relationships between them, and the identifiers you handed to customers will still be there after all of that, because every rewrite has to carry the data forward and the data is what the business runs on.

CodeRewriteRewriteData model
Every rewrite has to carry the data forward, and the data is what the business runs on.

Which makes a small number of early modelling decisions genuinely one-way doors, and worth treating differently from everything else you'll decide in year one.

The decisions that are actually irreversible

Most schema choices are fine and changeable. These four are the ones I'd slow down for.

Tenancy. Whether a row belongs to one customer, or to several, or to a hierarchy of them. Retrofitting multi-tenancy onto a single-tenant model touches every query, every index, and every authorisation check in the system, and getting one of them wrong leaks one customer's data to another. If there's any chance you'll sell to organisations rather than individuals, put the tenant on everything from day one, even when there's exactly one tenant.

Identity. What a "user" is, and whether it's the same object as an account, a person, a login, and a subscriber. These get conflated in week two because at the time they're the same thing. They stop being the same thing the first time someone needs two logins, or one person belongs to two organisations, or a company wants a shared account. Separating them later is a migration that touches authentication, which is the least fun migration available.

Cardinality assumptions. Anywhere you've assumed one where the world eventually says many. One address per customer. One currency. One payment method. One workspace. Each is a single field that becomes a table, and each conversion ripples through every piece of code that read the field.

Anything you've exposed externally. Identifiers in URLs, in webhooks, in exports, in API responses. Once a customer's script depends on your ID format, it's a public contract, and you'll be maintaining it after you've replaced everything behind it. Use opaque identifiers you can remap, and don't leak sequential integers that tell people how many customers you have.

Naming, which is not a cosmetic issue

The words you pick for your core entities become the words the company thinks in.

If you call something a "job," then five years later every conversation in sales, support, and engineering is about jobs, and the concept has hardened whether or not it was right. Renaming a core entity is not a rename. It's a migration through documentation, UI, API, internal vocabulary, and everyone's mental model, and most companies never do it.

Which argues for a specific discipline early: take the names from the domain rather than from the implementation. If the people who use your product call it a shipment, call it a shipment, not a transaction. The cost of a mismatch is a permanent translation layer in every conversation between engineering and everyone else.

The other rule: don't name things after what they currently are if that's a coincidence. "Enterprise plan" as an entity, rather than "plan with these attributes," bakes today's pricing into your schema.

Migrations at scale, in practice

Once you have real data and real traffic, every schema change is a project rather than a statement, and there's one pattern that covers most of it.

Expand, migrate, contract. Add the new structure alongside the old one. Write to both. Backfill the historical data in batches, slowly enough that you don't take out the database. Move readers to the new structure. Verify. Then, and only then, stop writing the old one, and much later, remove it.

Each step is independently reversible, which is the point. A big-bang migration with a maintenance window is a bet that everything works, resolved at 3am with no way back.

Three things people learn the hard way. The backfill takes longer than expected, always, and needs to be resumable, because it will be interrupted. The double-write period is where bugs live, because two writes can partially fail, so you need a reconciliation check rather than a hope. And the contract step gets skipped, permanently, because it's risky and unrewarding, which is how systems end up with four generations of half-removed structure. Put the removal on the calendar with a name against it.

The reporting model you will eventually need

Every company reaches a point where someone wants numbers, and the numbers come out of the production database, and then either the queries are slow or the database is.

That moment is predictable and the trajectory is always the same. First a read replica, which works for a while. Then somebody writes a query that takes eleven minutes. Then you have a set of views nobody understands, and a weekly report that occasionally locks the checkout table.

What's actually going on is that your transactional model is optimised for writing one thing correctly, and reporting wants to read everything cheaply. Those are different problems and no schema does both well.

You don't need a warehouse on day one. You do need to see it coming, and the cheap early move is to make sure your events and your state changes are recorded in a form you could later replay: timestamps on everything, no destructive updates on the things you'll want history for, and a record of what happened rather than only what is currently true.

That last point is the one worth spending money on early. A system that stores only current state has thrown away its own history, and no amount of later investment gets it back. You'll want to answer "what did this look like in March" and the answer will be that nobody knows.

What to do in week one of a new product

Spend an afternoon, not a week, on this specific list.

Write down what your three or four core entities are, in domain words. Draw the relationships and mark every place you've assumed one-of-something. For each assumption, ask whether many is plausible within three years, and if it is, model it as many now, because the cost today is small and the cost later is not.

Then put a tenant identifier on everything. Then decide what's exposed externally and make those identifiers opaque.

That's it. Everything else can be refactored later, and most of it will be.