Module 8: Project Define Mercados Strategy
The moat layer
Description
The one-pager's fourth layer answers the question left open at the end of the previous lesson: Mercado's competitive space is open today, but it has an expiration date — what, exactly, is going to defend it when someone seriously tries? This lesson runs moatScore on module 6's complete inventory of eight candidates — not just the two most-repeated ones, the entire inventory — and fills the one-pager's moats layer with a verdict that allows no shortcuts: real moat, weak moat, or, in all honesty, not a moat yet.
Connection to the module. This lesson reuses moatScore and the complete eight-candidate inventory verbatim from module 6, with no changes. This layer's result is the input lesson 8 is going to cross against the strategic filter: a bet that belongs to the strategy but doesn't deepen any real moat isn't a bad bet, but it is one the team should look at differently.
An everyday analogy: inspecting the whole castle, not just the most photographed tower
Module 6 opened with the image of two castles that look almost identical from the road, and closed with a military engineer walking the entire castle, structure by structure, without being impressed by the prettiest facade or discouraged because a structure had no fancy name. This one-pager layer inherits that exact standard: it's not enough to audit the two moats most mentioned in the team's hallway conversations (sellerNetwork, purchaseData) — the same criterion has to be applied to all of the inventory, including the differentiation the previous lesson just celebrated with solid evidence.
Worked example: the complete audit, eight candidates, one criterion
We run moatScore on the complete inventory: four candidates you already know by name (sellerNetwork, purchaseData, fasterCheckout, curatedDiscovery — this last one, the differentiation lesson 4 just confirmed as real) and four more (logisticsNetwork, sellerToolsWorkflow, localSellerTrust, mercadoBrand).
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: 'sellerNetwork', type: 'networkEffect', sides: 2, localDecay: false },
{ name: 'purchaseData', type: 'dataMoat', feedbackLoop: true, uniqueToUs: true },
{ name: 'logisticsNetwork', type: 'scaleEconomies', fixedCostShare: 0.8 },
{ name: 'sellerToolsWorkflow', type: 'switchingCost', depth: 'dataAndWorkflow' },
{ name: 'localSellerTrust', type: 'brand', pricingPower: true },
{ name: 'curatedDiscovery', type: 'feature', timeToCopyWeekends: 3 },
{ name: 'fasterCheckout', type: 'feature', timeToCopyWeekends: 1 },
{ name: 'mercadoBrand', type: 'brand', pricingPower: false },
];
console.log('=== moats: Mercado\'s complete audit ===\n');
const audit = candidates.map(moatScore);
console.table(audit);
const realMoats = audit.filter((a) => a.verdict === 'moat');
const weakMoats = audit.filter((a) => a.verdict === 'weak-moat');
const notMoats = audit.filter((a) => a.verdict === 'not-a-moat');
console.log(`\nReal moats (${realMoats.length}/${candidates.length}): ${realMoats.map((a) => a.name).join(', ')}`);
console.log(`Weak moats (${weakMoats.length}/${candidates.length}): ${weakMoats.map((a) => a.name).join(', ')}`);
console.log(`Not a moat (${notMoats.length}/${candidates.length}): ${notMoats.map((a) => a.name).join(', ')}`);
What to expect. Running the file with Node produces exactly this output:
=== moats: Mercado's complete audit ===
┌─────────┬───────────────────────┬──────────────────┬────────────┬──────────────┬──────────────────────────────────────────────────────────────────────────┐
│ (index) │ name │ type │ durability │ verdict │ rationale │
├─────────┼───────────────────────┼──────────────────┼────────────┼──────────────┼──────────────────────────────────────────────────────────────────────────┤
│ 0 │ 'sellerNetwork' │ 'networkEffect' │ 8 │ 'moat' │ 'network effect 2-sided, no decay' │
│ 1 │ 'purchaseData' │ 'dataMoat' │ 9 │ 'moat' │ 'the data feeds a loop that improves the product and is exclusive' │
│ 2 │ 'logisticsNetwork' │ 'scaleEconomies' │ 8 │ 'moat' │ 'economies of scale with 80% fixed cost' │
│ 3 │ 'sellerToolsWorkflow' │ 'switchingCost' │ 8 │ 'moat' │ "switching cost of depth 'dataAndWorkflow'" │
│ 4 │ 'localSellerTrust' │ 'brand' │ 6 │ 'weak-moat' │ 'the brand changes purchase behavior (tolerates price or friction)' │
│ 5 │ 'curatedDiscovery' │ 'feature' │ 3 │ 'not-a-moat' │ 'feature copyable in ~3 weekend(s)' │
│ 6 │ 'fasterCheckout' │ 'feature' │ 1 │ 'not-a-moat' │ 'feature copyable in ~1 weekend(s)' │
│ 7 │ 'mercadoBrand' │ 'brand' │ 2 │ 'not-a-moat' │ 'the brand is recognized but doesn't change purchase behavior' │
└─────────┴───────────────────────┴──────────────────┴────────────┴──────────────┴──────────────────────────────────────────────────────────────────────────┘
Real moats (4/8): sellerNetwork, purchaseData, logisticsNetwork, sellerToolsWorkflow
Weak moats (1/8): localSellerTrust
Not a moat (3/8): curatedDiscovery, fasterCheckout, mercadoBrand
This layer produces the whole one-pager's most uncomfortable, and most important, finding: curatedDiscovery — the real differentiation lesson 4 just confirmed with solid evidence, the very heart of Mercado's value proposition — comes out durability: 3, 'not-a-moat'. This doesn't contradict the previous lesson: the differentiation is still real, still serves the segment better than the alternatives, and is still the exact reason Mercado wins the explorers segment today. What this result says, precisely, is that this advantage isn't protected yet: it lives today as an algorithm any competitor with a good engineering team could replicate in a few weeks, not as a structural mechanism. Four real moats do cross the threshold —sellerNetwork, purchaseData, logisticsNetwork, sellerToolsWorkflow— each through an independent mechanism, and none of them is the differentiation the segment actually perceives today.
Deep dive: differentiation and moat are different layers, on purpose
This is the central tension lessons 4 and 5 together expose, and that neither one, alone, could show you: real differentiation (lesson 4) answers "do we win today, against today's rivals?" — and the answer, for curatedDiscovery, is a resounding yes. Moat (this lesson) answers a completely different question: "will it still be ours if someone seriously attacks it?" — and the answer, for that same curatedDiscovery, is not yet. A team that only looks at differentiationMap would feel completely safe; a team that only looks at moatScore might conclude, wrongly, that Mercado "has nothing real." Both readings are incomplete. The complete truth —real differentiation, today without structural protection— only appears when you run both layers and read them together, exactly as you just did.
Common mistakes
Auditing only module 6's two "famous" moats and skipping lesson 4's differentiation. What happens: the team repeats the analysis of sellerNetwork and purchaseData —the examples most repeated in module 6— and never subjects curatedDiscovery (the central differentiation from this very module's previous lesson) to the same criterion. Why it happens: repeated examples feel "already solved," and the just-confirmed differentiation feels "already proven" by lesson 4 — subjecting it to a different criterion again feels redundant. How to spot it: if your moat inventory doesn't explicitly include every dimension differentiationMap marked as real differentiation, you have a blind spot exactly where it matters most. How to fix it: this lesson's inventory should always include, at minimum, every pillar the howToWin layer just confirmed — it's the most important connection between the two layers.
Collapsing weak-moat into the same category as moat or not-a-moat. What happens: presenting the result, someone simplifies to "we have five moats" (adding localSellerTrust to the four real ones) or, in the other direction, "we only have four things worth anything" (dismissing localSellerTrust along with the features), losing the intermediate verdict's specific information. Why it happens: communicating three categories is more awkward than communicating two, and the temptation to simplify erases exactly the nuance the model worked to capture. How to spot it: if your moats layer summary uses only two categories where the model produced three, you lost real information in translation. How to fix it: always communicate all three groups separately, with weak-moat explicitly marked as "real but fragile, candidate for deepening."
Closing the layer without naming what it would take for curatedDiscovery to become a moat. What happens: the team accepts the curatedDiscovery: not-a-moat result as a fixed fact, without asking what would change that verdict, and keeps treating that differentiation as if it were already protected. Why it happens: the model delivers a binary verdict per candidate (moat / weak-moat / not-a-moat), and it's easy to read it as a permanent state instead of a snapshot of the current design. How to spot it: if nobody on the team can name, after seeing this audit, a concrete architecture change that would move curatedDiscovery from 'feature' to another type, the audit stayed pure diagnosis. How to fix it: connecting curatedDiscovery to the same data loop already proven to work in purchaseData (feedbackLoop: true, durability: 9) would move that differentiation from type 'feature' to 'dataMoat' — the same path module 6 already pointed to, and that lesson 8 of this module is going to explicitly flag as the final roadmap's most urgent gap.
Exercises
Exercise 1 — Add a ninth candidate. Mercado is evaluating launching a recommendation system that learns from each specific user's purchase history (not just general trends), feeding directly into the search ranking. What type would you assign it, with what parameters, and what verdict would you expect?
See solution
A reasonable version: { name: 'personalizedRanking', type: 'dataMoat', feedbackLoop: true, uniqueToUs: true } — it describes exactly the pattern that makes purchaseData a real moat: the data feeds back into the product (the ranking improves with every purchase) and is exclusive to Mercado (nobody else has that specific history). With those parameters, durability would be 7 + 2 = 9, verdict: 'moat' — the same result as purchaseData, because it's, in essence, an extension of the same mechanism.
Exercise 2 — The erosion scenario for sellerToolsWorkflow. If Mercado migrated its seller tools to a simpler, easier-to-abandon platform (depth: 'habit' instead of 'dataAndWorkflow'), what would happen to the verdict?
See solution
depthScore['habit'] is 5, compared to depthScore['dataAndWorkflow'] which is 8. durability would drop from 8 to 5, and the verdict would fall from 'moat' to 'weak-moat'. It's a direct illustration of an architecture decision —how deeply you integrate a user's data and workflow— that changes, with the same formula, whether something crosses the real-moat threshold or not. The decision to "simplify" a tool can, without anyone noticing at the time, weaken a real moat.
Exercise 3 — Present the uncomfortable finding to the founding team. Write, in a paragraph, how you'd explain to Mercado's founding team that its central differentiation (curatedDiscovery) still isn't a moat, without it sounding like lesson 4 (where they celebrated it as a real advantage) was wrong.
See solution
A sample answer: "The differentiation we confirmed in the previous layer is still completely real — we win the segment today, with a clear margin, thanks to curatedDiscovery. What this audit adds isn't a correction, it's a different layer of information: that advantage, today, lives as a good algorithm, not as something a well-resourced competitor couldn't replicate in a few weeks. It's not that we're losing — it's that we haven't yet built the part that turns winning today into still winning a year from now. The good news is we already know exactly what it would take: connecting the curation to the same purchase-data loop we've already proven works elsewhere in the product."
Summary and next step
In this lesson you filled the one-pager's fourth layer: moats, audited over the complete eight-candidate inventory, with no exceptions for what's repeated or celebrated. The result: four real moats through four distinct mechanisms, one real-but-fragile weak moat, and the finding that connects directly to the previous lesson — Mercado's central differentiation, curatedDiscovery, still isn't protected by any structural mechanism.
Before moving on you should be able to: explain why real differentiation and moat are different questions, and name the concrete path that would move curatedDiscovery from 'feature' to 'dataMoat'.
Lesson 6 fills the fifth layer: the strategic filter, applied to Mercado's complete backlog — the question of which bets belong to the game the previous four layers just defined.
Resources
- Hamilton Helmer, 7 Powers — 7powers.com. The complete technical vocabulary behind this audit's four real moats — network effects, switching costs, economies of scale, data. In English.
- Investopedia, "Economic Moat" — investopedia.com/terms/e/economicmoat.asp. The complete moat metaphor, worth rereading with Mercado's eight-candidate inventory already classified. In English.
- Ben Thompson, "Aggregation Theory" — stratechery.com/aggregation-theory. The underlying argument about data and network effects as digital moats — the same mechanism that separated
purchaseData(real moat) fromcuratedDiscovery(not yet) in this audit. In English.