Is the Database Really a Detail?
One camp insists the database is a detail behind a boundary. Anyone who has tried to split a schema knows data decomposition is the hardest problem in the whole architecture. Both are right — about different data — and the axis that reconciles them decides which one applies to you.
The team did everything the doctrine said. Every query behind a repository interface. The domain importing nothing from persistence. A fitness function failing the build if it ever did.
Then they tried to split the schema, and it took nine months.
The abstraction was never the problem, and it was never going to help. There are two positions here that sound like flat contradictions of each other, and both are held by people who have shipped a lot of systems. The disagreement is worth taking seriously rather than resolving by seniority.
The claim
The clean-architecture position is unambiguous: the database is a detail. It sits at the outer ring, behind an architectural boundary, and business rules must not know it exists. The choice should be deferrable — you should be able to build and test the core before deciding whether it is Postgres or Mongo, and swap it later by writing a new adapter.
The strong version of this is genuinely correct, and worth defending against the eye-roll it sometimes gets:
- The domain stays testable without infrastructure. No Docker to run a unit test.
- The ORM does not shape the model. Your
Orderis not a row wearing a class. - The decision is deferrable, which matters most exactly when you know least.
Any team that skips this ends up with business rules expressed as SQL and a domain nobody can exercise in isolation. Keep the repository interface. It earns its place.
What the abstraction does not buy
Here is where the claim gets overextended.
A repository interface abstracts the access mechanism — how you read and write. It does not abstract the data — what is stored, who owns it, and what is transactionally consistent with what.
Swapping Postgres for Mongo is not a matter of writing a new adapter, because the moment you chose your aggregate boundaries and what commits atomically, you made a decision about the data model, and it leaked into the domain regardless of how clean the code boundary was. Aggregate design assumes a consistency boundary. A document store with no cross-document transactions does not offer the one you assumed.
Anyone who has actually pulled a running architecture apart has met the other half of this, and it is not a footnote: data decomposition is the hardest part of the job. Not the services — the data. This is why the useful unit of independent deployability, the architecture quantum, is defined partly in terms of static coupling: a service plus the database it cannot function without is a single quantum, because a service that has no data is not operational.
Two services sharing a schema are one quantum no matter how immaculate their repository interfaces are. The abstraction is invisible to that fact.
The axis that reconciles them
The two positions stop conflicting the moment you separate the kinds of data:
- Operational data is what the business runs on — orders, transactions, inventory, balances. Interrupt it and the company stops trading within the hour.
- Analytical data is what the business learns from — the warehouse, the dashboards, the models. Interrupt it and nobody notices until the Monday report, because it serves long-term direction rather than day-to-day operation.
Now the disagreement dissolves:
For operational data, ownership is architecture. Who owns the customer record is not a detail behind a boundary — it defines your quanta, your transactional scope, and what can deploy independently. No interface abstracts it away, because the dependency is operational: the service does not start without it.
For analytical data, the detail framing largely holds. A warehouse, a read replica, a projection — swap the engine, change the format, move it to a different store, and the operational system is unaffected. Nobody needs it to boot.
So: "detail" is a claim about which database. It is not a claim about whose. The first question is frequently a detail. The second is architecture, and always was.
What follows in practice
Draw the data-ownership boundary first. Which bounded context owns this operational data, exclusively? That decision constrains your service boundaries, not the other way round. Teams that split services first and data later discover they built twelve deployables in one quantum.
Keep the repository interface anyway. Everything in the "strong version" above is still true and still worth having. The mistake is not writing the abstraction; it is believing it discharged the data question.
Be honest about what "swappable" means. You can swap the driver cheaply. You can swap the consistency model only by revisiting your aggregate boundaries. Say which one you mean when you claim the database is replaceable.
Use the operational/analytical split deliberately. Sharing an analytical replica across many consumers is fine and does not merge quanta. Sharing the operational store does. Most "shared database" arguments never make that distinction, which is why they never resolve.
The takeaway
Both positions are right, and the useful move is not to pick a champion — it is to notice which question is on the table.
"The database is a detail" is true of the access mechanism and false of the data.
When someone says the database is swappable, ask which they mean. If they mean the driver, agree and move on. If they mean the data — who owns it, what commits with what — then you are not discussing a detail. You are discussing the architecture, and the repository interface will not help you.