Module 6: Moats And Defensibility
Data and scale moats: when bigger and more-used is, genuinely, better
Description
This lesson opens the two remaining moat types before reaching the model's control group (lesson 6). We group them together because they share a surface-level intuition —"the bigger and more used, the better"— that, in both cases, turns out to be true only under one precise condition, not automatically. A dataMoat isn't "having a lot of data" — it's that data feeding a loop that improves the product. A scaleEconomies isn't "being a big company" — it's that a real portion of the cost is fixed, so every additional unit comes out cheaper. Without that condition, both stay as size without advantage: a file full of records nobody uses, or a large operation whose cost grows at the same pace as its revenue.
Connection to the module. Lesson 2 already scored purchaseData with durability: 9 without fully opening up the mechanics of feedbackLoop and uniqueToUs — this lesson opens that up, and adds the scaleEconomies type, which you haven't seen executed until now. Lesson 6 takes these two types, along with the other three already covered, and puts them next to the control group —feature— to close the module's central question.
An everyday analogy: buying wholesale, and the librarian who remembers you
Two analogies, one per type, because each one compounds differently.
Economies of scale: buying wholesale. A family buying rice in one-kilo bags pays, per kilo, more than a restaurant buying fifty-kilo sacks. It's not that the restaurant negotiates better because it's friendlier — it's that the cost of going to the supplier, negotiating the price, and organizing storage is, for the most part, fixed: it costs almost the same to make that trip to buy one sack as to buy ten. The restaurant spreads that fixed cost across fifty kilos; the family carries it whole on just one. That's the essence of a real economy of scale: not "we're big," but "a significant part of our cost doesn't grow at the same rate as our volume."
Data moat: the librarian who remembers you. A huge library, with a massive catalog but a new librarian every week who doesn't know you, offers you size but nothing personal — every visit starts from zero. A small librarian who's been there ten years, and who remembers you asked for a certain book, that you liked it, and who suggests something similar next time before you even ask, has an advantage that doesn't depend on catalog size — it depends on every loan feeding the next recommendation, over and over, refining itself over time. That cycle —you asked, you liked it, I learn, I suggest better— is exactly what separates data that accumulates from data that feeds back.
Worked example: four advantages, two mechanisms, the same question about the loop
We reuse moatScore unchanged. Two dataMoat-type candidates: purchaseData, the purchase data you already know from lesson 2, with feedbackLoop: true because it directly feeds the recommendation engine, and browsingHistoryNoLoop, the page-view and search history Mercado also stores, but that today doesn't connect to any system that acts on it — it accumulates in a database and sits there. Two scaleEconomies-type candidates: logisticsNetwork, the warehouse and delivery-route network Mercado built, where the cost of negotiating with carriers and maintaining the infrastructure is, mostly, fixed — fixedCostShare: 0.8; and customerSupportTeam, the customer support team, which grows nearly proportionally with order volume —more orders, more agents are needed— so most of its cost is variable, not fixed — fixedCostShare: 0.2.
// Pedagogical model: scores the DURABILITY (0-10) of a competitive advantage.
// Reused unchanged from lesson 2 -- this lesson digs into
// dataMoat (feedbackLoop, uniqueToUs) and scaleEconomies (fixedCostShare).
function moatScore(advantage) {
const { name, type } = advantage;
let durability;
let rationale;
switch (type) {
case 'networkEffect': {
const { sides, localDecay } = advantage;
durability = sides >= 2 ? 8 : 5;
if (localDecay) durability -= 3;
rationale = `network effect ${sides}-sided${localDecay ? ', with local decay' : ', no decay'}`;
break;
}
case 'switchingCost': {
const { depth } = advantage;
const depthScore = { contractual: 3, habit: 5, dataAndWorkflow: 8 };
durability = depthScore[depth] ?? 3;
rationale = `switching cost of depth '${depth}'`;
break;
}
case 'scaleEconomies': {
const { fixedCostShare } = advantage;
durability = Math.round(fixedCostShare * 10);
rationale = `economies of scale with ${Math.round(fixedCostShare * 100)}% fixed cost`;
break;
}
case 'dataMoat': {
const { feedbackLoop, uniqueToUs } = advantage;
durability = feedbackLoop ? 7 : 2;
if (feedbackLoop && uniqueToUs) durability += 2;
rationale = feedbackLoop
? `the data feeds a loop that improves the product${uniqueToUs ? ' and is exclusive' : ''}`
: 'the data accumulates but doesn\'t feed back into the product';
break;
}
case 'brand': {
const { pricingPower } = advantage;
durability = pricingPower ? 6 : 2;
rationale = pricingPower
? 'the brand changes purchase behavior (tolerates price or friction)'
: 'the brand is recognized but doesn\'t change purchase behavior';
break;
}
case 'feature': {
const { timeToCopyWeekends } = advantage;
durability = Math.max(0, Math.min(3, timeToCopyWeekends));
rationale = `feature copyable in ~${timeToCopyWeekends} weekend(s)`;
break;
}
default: {
durability = 0;
rationale = 'unknown advantage type';
}
}
durability = Math.max(0, Math.min(10, durability));
const verdict = durability >= 7 ? 'moat' : durability >= 4 ? 'weak-moat' : 'not-a-moat';
return { name, type, durability, verdict, rationale };
}
const candidates = [
{ name: 'purchaseData', type: 'dataMoat', feedbackLoop: true, uniqueToUs: true },
{ name: 'browsingHistoryNoLoop', type: 'dataMoat', feedbackLoop: false, uniqueToUs: false },
{ name: 'logisticsNetwork', type: 'scaleEconomies', fixedCostShare: 0.8 },
{ name: 'customerSupportTeam', type: 'scaleEconomies', fixedCostShare: 0.2 },
];
console.log('=== Data and scale: does it feed back into the product? does fixed cost matter? ===\n');
console.table(candidates.map(moatScore));
What to expect. Running the file with Node produces exactly this output:
=== Data and scale: does it feed back into the product? does fixed cost matter? ===
┌─────────┬─────────────────────────┬──────────────────┬────────────┬──────────────┬───────────────────────────────────────────────────────────────────────┐
│ (index) │ name │ type │ durability │ verdict │ rationale │
├─────────┼─────────────────────────┼──────────────────┼────────────┼──────────────┼───────────────────────────────────────────────────────────────────────┤
│ 0 │ 'purchaseData' │ 'dataMoat' │ 9 │ 'moat' │ 'the data feeds a loop that improves the product and is exclusive' │
│ 1 │ 'browsingHistoryNoLoop' │ 'dataMoat' │ 2 │ 'not-a-moat' │ 'the data accumulates but doesn't feed back into the product' │
│ 2 │ 'logisticsNetwork' │ 'scaleEconomies' │ 8 │ 'moat' │ 'economies of scale with 80% fixed cost' │
│ 3 │ 'customerSupportTeam' │ 'scaleEconomies' │ 2 │ 'not-a-moat' │ 'economies of scale with 20% fixed cost' │
└─────────┴─────────────────────────┴──────────────────┴────────────┴──────────────┴───────────────────────────────────────────────────────────────────────┘
The two pairs tell the same story in different vocabulary. purchaseData and browsingHistoryNoLoop are, in volume, comparable — Mercado probably stores as much browsing history as purchase history —, but one feeds back into the product (feedbackLoop: true, every purchase adjusts future recommendations) and the other sits in the database with nobody connecting it to anything (feedbackLoop: false). The durability difference —9 versus 2— doesn't come from the size of the data, it comes entirely from the loop. logisticsNetwork and customerSupportTeam are, in annual spend, also comparable — both are large operations with real budgets —, but one has a high share of fixed cost that dilutes with volume (fixedCostShare: 0.8, the warehouse network costs almost the same to maintain whether it's 10,000 or 100,000 orders a month) and the other grows almost proportionally with volume (fixedCostShare: 0.2, every extra order needs, roughly, a bit more support time). The size of the budget didn't predict the result — the cost structure did.
Deep dive: two different ways "bigger" translates to "better"
It's worth naming precisely why these two types, even though they share the "size helps" intuition, fail for opposite reasons when they fail. A dataMoat fails from lack of loop: the most common trap, sometimes called vanity data, is accumulating records because "they'll be useful someday" without building the system that actually turns them into a product improvement — in that case, the data isn't an asset, it's a liability: it costs storage, it costs privacy risk, and it produces no advantage. A scaleEconomies fails from lack of fixed-cost leverage: the corresponding trap is confusing "we're a big company, with a lot of volume" with "every additional unit comes out cheaper" — a business can be huge and still be, structurally, a collection of variable costs that grow at the same pace as revenue, with no real economy behind the size. It's, in spirit, the same mistake lesson 3 named for network effects —"lots of users" isn't the same as "network effect"— now applied to data ("a lot of data volume" isn't the same as "data moat") and to operations ("a lot of business volume" isn't the same as "economy of scale").
It's also worth revisiting, now that the whole type is on the table, something lesson 2 already previewed in an exercise: uniqueToUs is a bonus, not a requirement, for a data moat. purchaseData gets the extra two points because, in addition to feeding back into the product, nobody else has exactly that data — but non-exclusive data, which in principle any competitor could collect on its own, still qualifies as 'moat' if feedbackLoop is true and the result exceeds the threshold of 7 (recall lesson 2's exercise: feedbackLoop: true, uniqueToUs: false gives durability: 7, right at the edge). The objection "but anyone could get this same data" doesn't invalidate a data moat by itself — what does invalidate it is the absence of the loop.
Common mistakes
Accumulating data without building the loop that connects it to the product. What happens: the data team proudly reports "we have petabytes of browsing history" in every quarterly review, treating volume as if it were, by itself, a strategic asset, with no recommendation, ranking, or pricing system actually using that data to improve the experience. Why it happens: collecting data feels like progress —there's a dashboard that grows every month—, while building the loop that turns it into value is a concrete engineering project, with an owner and a cost, competing for priority against everything else on the roadmap. How to spot it: ask "what product decision changes today, automatically, because of this data?" — if the answer is "none yet, but it could," feedbackLoop is false and the real durability is 2, no matter how many petabytes there are. How to fix it: prioritize building the loop —the pipeline that connects the data back to the product— before continuing to invest in collecting more of the same.
Confusing operation size with real economies of scale. What happens: the finance team points to a function's annual budget —support, logistics, whatever it is— as evidence of a scale advantage, without calculating what portion of that cost is actually fixed versus what grows proportionally with volume. Why it happens: a big budget looks impressive on a slide, and it's easy to assume "big" automatically implies "efficient by size," without doing the explicit fixedCostShare math. How to spot it: ask "if we doubled volume tomorrow, would this function's cost double too, or grow much less than that?" — if the answer is "it would double almost the same," fixedCostShare is low and there's no real economy of scale there, even if the budget is large. How to fix it: measure fixedCostShare explicitly for each function before calling it a moat — and, if it's low, look for the functions where it actually is high (like logisticsNetwork in the example) to concentrate investment where it genuinely compounds with size.
Treating data exclusivity as a requirement, not a bonus. What happens: someone in a strategy review dismisses a real data moat —with feedbackLoop: true— by saying "this doesn't count, any competitor could collect the same type of data if it wanted to," treating the lack of exclusivity as if it invalidated the whole moat. Why it happens: "exclusive" sounds like the word that makes something defensible, and it's easy to overlook that the model —and the logic behind it— weights the loop much more heavily than exclusivity. How to spot it: if the conversation centers on "could someone else have this data?" instead of "does this data actively feed back into the product?", the wrong criterion is driving the discussion. How to fix it: always go back to the feedbackLoop question first — it's the one that determines whether there's a moat or not; uniqueToUs only decides whether that already-existing moat is a bit stronger or a bit weaker.
Exercises
Exercise 1 — Classify the mechanism. For each situation, decide whether it describes a dataMoat with feedbackLoop, one without it, or a scaleEconomies with high or low fixedCostShare, and justify it in one sentence: (a) Mercado negotiated lower shipping rates with carriers because it moves a package volume no individual seller could negotiate alone; (b) Mercado stores a record of every click on every button in the app since 2020, with no system using it today; (c) every search a buyer makes on Mercado adjusts, in real time, which products show up first for them next time.
See solution
- (a)
scaleEconomieswith highfixedCostShare. The cost of negotiating and maintaining shipping contracts is, largely, fixed — negotiating with a carrier to move a million packages doesn't cost a million times what negotiating to move one does, so Mercado's volume translates into a per-package rate a small seller can't match. - (b)
dataMoatwithfeedbackLoop: false. It's exactly thebrowsingHistoryNoLoopexample: real data, accumulated over years, with no system turning it into a product improvement today — vanity data, not a moat. - (c)
dataMoatwithfeedbackLoop: true. The real-time adjustment is, literally, the loop: today's search feeds back into tomorrow's experience, regardless of whether that data is exclusive to Mercado.
Exercise 2 — Predict before running it. Without running code, using this lesson's scaleEconomies formula (durability = Math.round(fixedCostShare * 10)), predict the durability and verdict of this advantage: { name: 'warehouseAutomation', type: 'scaleEconomies', fixedCostShare: 0.65 }. Then verify by running moatScore on that object.
See solution
fixedCostShare: 0.65 gives durability = Math.round(0.65 * 10) = Math.round(6.5) = 7 (JavaScript's rounding of .5 goes up to the next integer for positive values), and 7 >= 7 gives verdict: 'moat' — right at the edge, just like the dataMoat exercise in lesson 2. The point of the exercise: the boundary between 'weak-moat' and 'moat' in scaleEconomies falls exactly at fixedCostShare: 0.65 — an operation where a bit less than two-thirds of the cost is fixed already crosses into real-moat territory, it doesn't need to be practically all the cost.
Exercise 3 — Turn vanity data into a data moat. Mercado has the complete history of reviews buyers leave about sellers, but today that history is only shown on the seller's page — it doesn't feed anything else. Propose, in two or three sentences, a concrete product change that would turn that history into a dataMoat with feedbackLoop: true, and explain which product decision would start changing automatically because of that change.
See solution
There's no single correct answer. A reasonable proposal: use the review history to automatically adjust the order in which sellers appear in search results within the same category —sellers with better recent reviews rank up, those accumulating complaints rank down—, so that every new review feeds back, in real time, into the decision of which seller a buyer sees first. The product decision that would start changing automatically is, precisely, the order of search results — today that decision probably depends only on signals like price or popularity; with the proposed change, every new review adjusts it a little, closing the loop that's currently missing.
Summary and next step
In this lesson you opened the two remaining types before the control group: the data moat, which requires a loop (feedbackLoop) and is only strengthened, not defined, by exclusivity (uniqueToUs); and the economy of scale, which requires a real portion of the cost to be fixed (fixedCostShare), not just for the operation to be large. Both share the trap of confusing size with advantage — a lot of data without a loop, or a lot of budget without fixed cost — and both are corrected with the same discipline: demand the exact mechanism, not the big number.
Before moving on you should be able to: explain why non-exclusive data can still be a real moat, calculate by hand the durability of an economy of scale given its fixedCostShare, and spot vanity data with a single question.
Lesson 6 closes the type-by-type tour with the model's sixth member, 'feature' — the control group that, by design, never crosses the threshold, and the exact reason why "we have feature X" defends nothing.
Resources
- Investopedia, "Economic Moat" — investopedia.com/terms/e/economicmoat.asp. Proprietary data and cost economies are both among the economic moat types in Morningstar's classification that this article summarizes — the same pair of types this lesson just ran in code. In English.
- Hamilton Helmer, 7 Powers: The Foundations of Business Strategy — 7powers.com. "Scale economies" is one of the book's seven sources of power, with the same criterion as this lesson: cost structure matters, not the size of the revenue figure. In English.