practice

Ownership-First Decomposition

also called Assign Owners Before Splitting, Logical Before Physical

Assigning each table a single owning team before splitting any code or data, because the ownership step costs nothing, removes the worst of the coupling immediately, and makes every subsequent step tractable.

chargebeedecompositiondatabasecouplingsequencing

The instinct when decomposing a system built on a shared database is to split the code or split the data. Both are expensive, both are hard to reverse, and both are premature.

The first step is free: assign each table to one owning team, with schema changes requiring their approval.

Why it matters

Shared mutable state is the form of coupling with no upper bound on participants: every consumer constrains every future change, and the cost grows with the pairs of teams rather than with the teams themselves. Ownership does not remove the coupling — it makes it governed, which stops the schema freezing and makes every later step possible.

It is skipped because it sounds like process rather than architecture, which is the same reason it delivers disproportionate value.

Implementation patterns

The ladder, in ascending cost:

  1. Assign ownership, and record it somewhere teams will look.
  2. Give other teams a read contract — an API, a replica, or a change-data-capture projection they own. Reads are usually the majority of the access and the easy half.
  3. Move writes behind the owner's interface. The expensive step, and the one that actually removes the coupling.
  4. Split the physical database, last and only if needed. Separate schemas or databases follow the logical separation rather than preceding it.

And to find the boundary: use change history. What has been deployed together, and what has ever broken together. That evidence takes ten minutes and is more reliable than any modelling exercise.

Industry example

A billing platform such as Chargebee illustrates both directions of error. Invoice generation and proration share money invariants and belong in one transactional boundary — separating them converts a local calculation into a distributed consistency problem for no benefit. Tax, dunning, accounting sync and document rendering are the natural extractions, because they change for different reasons at different cadences and none of them enforces an invariant the core needs.

Failure scenarios

  • Splitting data first, converting local joins into distributed ones before the boundary is validated.
  • Splitting code while sharing the databasethe most common intermediate state and worse than either endpoint, since it has all the deployment complexity of services and none of the independence.
  • No ownership, so the schema freezes because no change can be proven safe.
  • Separating components that share an invariant, creating a distributed consistency problem.
  • Boundaries chosen by domain modelling alone, ignoring the evidence in change history.

Trade-offs

Ownership without separation leaves the coupling in place: one team can still be blocked by another's migration, and lock contention still crosses team boundaries. It is a mitigation rather than a solution.

Its value is that it is nearly free and it converts a future rewrite into a future refactor. Teams that adopt it early, long before a split is needed, find the eventual decomposition dramatically cheaper — which is the argument for doing it at a point when it appears unnecessary.

Interview question

"Six teams share one database. You have one quarter and two engineers. What do you do, and what do you deliberately not do?"