There is a strong temptation when you start a serious software project to make the first milestone look impressive.

Create the dashboard.

Add a few realistic records.

Wire up a table.

Give everyone something they can click.

We did almost the opposite.

The first meaningful engineering milestone in a financial system we are building was a database environment designed to prove that the important business tables did not exist yet.

That sounds ridiculous until you understand what we were trying to protect.

A system can look finished long before it is trustworthy

Financial software gets dangerous when the interface gets ahead of the rules underneath it.

A table called investments can exist before anyone has settled what an investment actually means in the system.

A balance can appear on screen before the ownership history behind that balance is enforceable.

A distribution workflow can look functional before authorization, effective dates, reversals, or audit history are properly defined.

The screen creates confidence faster than the architecture earns it.

So we wanted a different first milestone.

Not “look how much exists.”

Look how clearly the boundary is enforced.

The bootstrap migration was intentionally a no-op

The database foundation included forward-only migrations, migration checksums, local target guards, a disposable test database, synthetic fixtures, and CI.

But the bootstrap migration itself did essentially nothing.

Then the database test verified that the environment came up clean and that no domain tables had appeared.

The empty schema was not unfinished work hiding behind a test.

It was the test.

We had built the machinery required to add financial state later without quietly inventing the financial model early.

Why this matters more with AI-assisted development

AI is very good at filling empty space.

Give an agent a product description and an empty repository and it can generate tables, routes, forms, types, APIs, and tests incredibly quickly.

That is useful.

It is also exactly why dependency boundaries matter more.

If the system needs a concept called “position history,” an AI coding agent can create a plausible version of it in minutes.

But plausible is not the same thing as approved.

Does ownership allow overlapping effective periods?

Can an old position be edited?

What creates the next version?

Which legal document controls the effective date?

What happens when two sources disagree?

Those questions are not boilerplate.

They are the product.

The database should make bad states difficult

One principle keeps surviving every architecture review we do:

Do not rely on application code to politely avoid impossible states when the database can make those states impossible.

That means important invariants eventually belong in constraints, relational structure, permissions, append-only history, and tests.

But you cannot write the right constraint before you have the right rule.

So sometimes the disciplined engineering move is to stop.

Write down the gate.

Prove the infrastructure.

Leave the table out.

“Not implemented” is useful information

One of the best things we started doing was being explicit about evidence states.

A design can be proposed without being accepted.

A contract can be accepted without being implemented.

Something can be implemented without being tested.

Something can be tested against synthetic data without being proven against a real integration.

And none of those automatically mean production-proven.

That vocabulary removes a lot of accidental exaggeration from a fast-moving build.

It also makes AI-assisted work easier to supervise because the next agent does not have to guess whether a document represents an idea, a decision, or running software.

The weird lesson

The empty database felt more professional than a prototype full of fake financial records would have.

Because it proved something concrete:

The engineering system existed.

The migration path existed.

The tests existed.

The safety boundaries existed.

And the financial model was still waiting for the dependencies required to make it real.

Sometimes progress is adding code.

Sometimes progress is building a system strong enough to say:

Not yet.