Rome and Boston
Rome. Objectville Pizza Store branch number 7. Friday close. A perfect carbonara: cured guanciale from the supplier Antonelli, DOP pecorino from an affineur in Lazio, farm eggs, a Valoriani wood-fired oven preheated to 280°C on stone. The branch has closed its books in the black three years running. The manager knows what she's doing. Her diners know it too.
Boston. Branch 23. Same carbonara. Italian pancetta from the importer down at the port, aged parmigiano from the distributor who comes in every week, pasteurized eggs (local regulations), a Lincoln electric oven calibrated to 280°C on a perforated pan. Just as profitable. Just as good. Different manager, different supplier, different machine, same dish.
Both recipes work. In their own branches, both are perfect.
The problem shows up the day head office decides to open 38 new branches in six countries. The board's question is blunt: which of the two recipes do we replicate?
The right answer is neither. Both are tied to four concrete things: a specific supplier, a specific ingredient, a specific machine, and a person who knows how things work in that kitchen. If Objectville opens in Zurich, Antonelli doesn't deliver there. The Swiss power grid can't handle the Boston oven. The Rome manager doesn't teach in German. Neither does the Boston one. The perfect recipe is perfect inside its branch. Outside, it doesn't scale.
It's not the recipe's problem. It's a problem of how it's written.
And this is the fine line that separates Block 1 from Block 2 of this series.
In Block 1 we focused on writing the recipe down — going from an ambiguous Word doc to a declarative artifact the business could write and the platform could read. We solved that problem in Week 2. Week 5 closed out the three-table restaurant: perfect craftsmanship, guaranteed quality, glass ceiling included. And there we said that this week we'd open the franchise.
What many data architecture series don't tell you is that a written recipe isn't enough to scale. A recipe can be perfectly declared and still be tied to four things that don't replicate. That's the question for Block 2: once you have the contract written down, how do you write it so it scales?
And the answer has had a specific name in software engineering for decades. We'll get there, but first let's take inventory of the four things that tie down the concrete recipe.
The four coupled dependencies
Go back to the Rome recipe. The perfect one. Look closely and the recipe doesn't just say what a carbonara is. It also says:
- Who executes it — the Rome manager. The one who knows how long the egg takes to set in the residual heat of the plate. The one who can tell, without measuring, when the guanciale has rendered enough fat to coat the pasta. Tacit knowledge, deposited in one specific person.
- What ingredient it uses — Antonelli guanciale, pecorino from Lazio, eggs from supplier X. Brands, formats, origins. If Antonelli shuts down tomorrow, the recipe as written stops working. It's not that the ingredient can't be substituted — it's that the recipe has no room for the substitute.
- What machine prepares it — Valoriani oven, wood, stone, 280°C. The recipe takes for granted that the machine cooks with a wood-fired profile. In a Lincoln electric oven in Boston, the same 280°C means something else. The heat curve is different, the humidity is different, the result is different. The Rome recipe doesn't say “280°C radiant cooking”: it says “280°C in my oven”.
- What service provider — Antonelli delivers on Mondays and Thursdays. The franchise depends on its distribution schedule, its restocking capacity, its contract with Objectville. Four variables outside the branch's control, yet bolted onto the recipe.
Four dependencies. One recipe. If any one fails, the dish doesn't go out.
And before going further, it's worth translating this into the conversation we're really having — the one about data, not pizza:
| In the pizzeria | In your warehouse |
|---|---|
| Who executes it | The senior data engineer with fifteen years on the system; the one who knows by heart what the COD_SITUACION field means |
| What ingredient it uses | The specific engine: Oracle 12c, BigQuery, Snowflake, with its data types, its dialects and its quirks |
| What machine prepares it | The transformation tool: Informatica, dbt, SQLMesh, with its conventions and its limits |
| What service provider | The hand-rolled ingestor, the legacy ETL, the nightly job someone scheduled in 2014 that nobody has dared to touch since |
Four dependencies bolted into any serious data project. The remarkable thing is that you can have all of them solved and still not scale. Your data engineer knows the system, the engine is paid for, the tool works, the ingestor has been running for years. And tomorrow a new domain comes in, and the queue starts all over again — because the next table depends on the same four proper nouns.
It's not a people problem. The Rome manager is excellent. The senior data engineer is excellent. Antonelli delivers on time. Oracle 12c works. It's a design problem: the recipe — written down or not — is coupled to the concrete mechanics that bring it to life.
This, in architectural terms, is what keeps the central data team as the bottleneck even when it's already writing contracts in declarative form. The Recipe from Week 2 was the first step. Writing it isn't enough; you have to write it so that the four dependencies are inverted.
What scales is inverting all four
What makes a franchise scale isn't loosening the four dependencies so the recipe tolerates variations. It's inverting them.
Inverting them means: the recipe stops talking about what I use and starts talking about what I need.
The Zurich manager doesn't write “Valoriani wood-fired oven at 280°C, stone”. She writes “radiant cooking at 280°C, a baking surface that holds 220°C, no direct electrical contact with the base”. That's what she needs. Head office decides which oven meets that spec in Switzerland, which supplier distributes it, which calibration fits the local voltage. If a better oven comes out tomorrow, the recipe doesn't change: head office swaps the adapter.
The manager doesn't write “Antonelli guanciale”. She writes “pork jowl cured for at least 8 weeks, fat content between 60% and 70%, no added nitrites”. That's what she needs. Head office decides which supplier meets that spec in each country.
And the person executing stops being indispensable, because she no longer carries the tacit knowledge in her head. The knowledge is in the recipe. The Zurich manager learns to read the recipe. So does the Tokyo manager. The knowledge is transferable because it no longer lives in a person — it lives in the contract.
When this is done right, the recipe written in Rome is enough to open Zurich, Tokyo, Buenos Aires and Lagos. The recipe isn't replicated with changes — it's replicated verbatim. What changes is the machinery behind it: which supplier, which machine, which calibration, who executes. And those changes aren't the recipe's problem — they're the central platform's problem, and its job is to make the dish come out the same whatever the continent.
Here's where the principle gets its name, just once, no book cited, because anyone who has written software knows it: this is dependency inversion. Don't let the pieces of a system depend on each other directly. Make them all depend on a stable, abstract contract. The contract is the anchor. Everyone pulls on it. Nobody pulls on anyone else directly.
The most familiar example — more familiar even than any franchise: imagine you buy a cookbook and the first page says “use the Smeg X45 oven, buy the tomatoes at the Safeway on Main Street, call Ramón, he's the flour guy”. You can't make it — not because you can't cook, but because the book doesn't give you requirements, it gives you proper nouns you don't control. If Ramón retires, the book breaks. That's not a recipe. It's a dependency dressed up as a recipe. The abstraction is the anchor. Nobody pulls on anyone else directly.
(For those coming from the software world: same principle as OpenAPI/Swagger — the YAML contract that frontend and backend share without calling each other directly. We mentioned it in Week 1.)
In the pizzeria, the abstract recipe is that anchor. In data architecture, that anchor has a name: the Recipe, the executable contract the domain writes and the platform reads. It's the piece Week 2 introduced, and the one this week we learn to write well.
The practical question that closes this section is straightforward: what does the business declare in a Recipe, and what does the platform resolve? Let's look at a real example.
The executable contract, in practice
Let's take a real table. It's called T_POLIZAS. It comes from the core insurance system of a regulated institution. It has 25 fields. All mixed together in the same row: customer data, broker data, product data, branch-office data, and data about the policy itself.
That's the photo of the pizza. The analyst who has spent fifteen years in Insurance looks at it and sees five concepts. The new engineer sees 25 columns with coded names and does what anyone would do with a photo: copies it as is. Nobody gave him the recipe — just a picture of the result.
And without the recipe, the dish can't be reproduced: you don't know which field changes over time and needs history, which one is a snapshot of a moment, which quality rule has to be met before accepting it, or which business entity owns each field. The photo tells you none of that. But the analyst knows — and the contract is where she declares it.
That act of recognition — which in the pizzeria would be “this is a carbonara, with four functional components: pasta, cured fat, cheese, egg” — is the first act of Domain Ownership. The domain does it, not the platform. The platform isn't going to guess.
And this is where the contract comes in. The domain declares, in an executable file, what has to be true about the data. It doesn't declare how it's materialized; it declares what it needs.
Looked at closely, the contract answers four questions — all in the domain's language:
Whose is this? Identification of the owner, domain, sensitivity, approval status, source behavior. Who owns what, in governance terms. In the traditional model this lives in a Confluence page nobody updates. Here it's mandatory: the platform generates nothing without this metadata.
What entities are there? A list of the identified business entities (Customer, Product, Broker, Branch Office, Policy) with their business keys. And a critical field that looks small and isn't: each entity declares whether it's global — that is, the same one that lives in other domains — or local.
When the Insurance domain declares Customer as global, it doesn't invent a new “insurance customer”. It connects to the Customer that already exists in the common catalog — the same one used by Risk, Billing or Complaints. Identity is shared; attributes still belong to the domain. Minimal kernel, maximal local context. Tomorrow, when Claims loads its own table, the platform will automatically know its Customer is the same person — without anyone deciding it in a meeting.
What attributes do they have, and what is their nature? Here the domain groups fields by entity and qualifies them with one word that changes all the downstream mechanics: their nature. Does this data change, and do I need history? Is it a snapshot of a moment? Is it an event that happened and doesn't get modified? Three different types, three different treatments in the warehouse. The analyst knows because she's been watching it for years. The customer's name changes — it needs history. Today's balance is a snapshot — it isn't modified; tomorrow's is added. A transaction happened — it isn't rewritten; it accumulates. The analyst declares it with one word. The platform infers everything else.
What rules must be met? Quality expressed in the domain's language, not in SQL. The tax ID has a valid format. The score is between 0 and 10. Net premium = Gross premium - Reinsurance, with a tolerance of 0.01. Three levels: property-level rules, entity-level rules, relationship-level rules. The analyst writes them by declaring them; the platform generates the tests and runs them on every load.
Those four blocks together make up the contract. It's JSON, yes — but JSON is the representation; it's not what matters. What matters is the split of responsibilities:
| What the business declares | What the platform resolves |
|---|---|
| Which entities exist and how they're identified | How each entity's technical key is generated — algorithm, seed, collisions |
| Whether an entity is global or local | How it connects to the common catalog of entities shared across domains |
| Which attributes each entity has and what their nature is | Which storage structure is created, with which load policy and which history |
| Which quality rules it must meet | Which SQL is generated, in which dialect, which engine runs it |
| Which domain it lives in and who owns it | Which permissions apply, which lineage is recorded, which audit trail is left |
On the left, what the domain knows and looks after — the logic of its business. On the right, what the platform encapsulates — the technical mechanics. The two columns are separated by a declarative contract. Exactly like the cookbook that specifies “220°C, 15% acidity”: if the platform switches engines tomorrow, the contract doesn't change. If the business extends an attribute, the platform adapts on its own.
That's the Recipe when it's written well. And written well means: with all four dependencies inverted. No proper nouns for suppliers, machines, SQL dialects or people. Only what the domain needs to be true.
How the two planes come apart
Let's go back to the pizzeria for a moment to nail the model down, because the image helps both the engineer and the CDO reading this.
A well-designed franchise — and we're not talking theory here; this has actually played out in publicly traded brick-and-mortar businesses, but that story will come — works because it separates two planes that most chains mix up.
The common plane is run by head office. It's industrialized, minimal and non-negotiable. Head office handles payroll, IT, distribution, contracts with shared suppliers, storefront format, the brand. And something critical: the canonical catalog of ingredients, machines and procedures, expressed in abstract terms. Radiant cooking at 280°C. Cured jowl with 60% to 70% fat. Durum wheat semolina pasta. A catalog, not a specific supplier.
The local plane is decided by each branch. It's autonomous, open and owner of its context. The Zurich branch decides which pizza it sells, where it puts it on the menu, how many it makes, at what price. The Tokyo branch decides the same. Rome keeps making carbonara. But none of the three has to fight head office over which oven to use — that's settled in the common plane.
The remarkable thing is that both exist at once, without clashing, because they live on different planes. Head office isn't flexible — it's minimal. The branch isn't governed — it's autonomous over what's its own. Governance sits below, in the common plane; decisions sit above, in the local plane.
When the two planes get mixed, everything collapses. The chain that imposes a planogram from head office suffocates its stores and turns cookie-cutter — and dies when neighborhood habits change faster than head office's review cycle. The chain that decentralizes without a common standard splinters into silos: every store does what it wants, no customer recognizes the brand, suppliers become impossible to manage.
Separating the two planes correctly is exactly what defines Domain Ownership in data architecture. The domain owns what's its own: which entities matter, which rules it applies, what quality it expects, what it calls the things it models. The platform owns what's common: everything needed for the domain's contract to materialize without the domain having to build it.
And the two coexist without clashing because they're separated by the contract — the Recipe — which each domain writes in its own language and the platform resolves underneath.
That is executable Domain Ownership.
What's next
For those operating in regulated industries — banking, insurance, energy, healthcare — there's a side effect worth noting: when the contract is executable, lineage isn't hunted down in an Excel file; it's read from the contract that generated the table. The owner isn't something you ask an intern; it's declared in the JSON. A field's sensitivity isn't documented in Confluence; it travels with the field through the entire pipeline. Compliance becomes a consequence of the design, not a bolted-on project. When the next regulation arrives — and it will — nobody will have to rewrite the model. You'll just recompile the contract.
But a contract does nothing on its own. Someone has to read it and materialize it. And the question several of you left in the comments — how do you technically implement a pantry? — I'll answer next week when we step into the central warehouse. One pillar at a time. Each pillar, executable. By the end of the block, a Data Mesh that doesn't collapse.
Next week we step into Objectville's central warehouse. And here's a sneak peek at the twist: remember the noodles with pizza sauce from Week 1? When the restaurant becomes a franchise, that pizza with noodle sauce can come back. For a different reason. Because when there are robot arms stacking boxes in the warehouse, none of them has any judgment. If there's noodle sauce on the shelf, it'll make you a pizza with noodle sauce. And serve it with academic confidence.
One more thing before I wrap up. What we're describing in this block — the separation of two planes, dependency inversion, the branch that owns its context — isn't theory. It actually happened, in a publicly traded brick-and-mortar business, with public numbers. But that story gets its own day, and it isn't today. Today, the contract. Next time, the structural pieces that make the central warehouse work — and why, without all of them, the robot arm ends up serving pizza with noodle sauce.