Module 6: Moats And Defensibility

Switching costs: what it costs to leave, not what it costs to stay

Description

A switching cost is the friction —in money, in time, in data, or in habit— a user faces when leaving your product for a competitor's. It's easy to confuse with lesson 3's question: a network effect explains why a user arrived and stayed because others were already there; a switching cost explains why, even if a competitor launched something objectively a bit better tomorrow, that same user wouldn't move — not because Mercado is irreplaceable, but because leaving costs something real, and that cost isn't paid by Mercado, it's paid by the user who decides to switch.

This lesson opens the second of the five moat types and, with it, the most important distinction of the topic: not all switching costs are equal, and the one that feels strongest on paper —a signed contract— is, according to the model, the weakest of the three. You're about to understand why.

Connection to the module. Lesson 3 worked on the whole network —how users attract each other. This lesson looks at the individual user, already inside, and asks something different: if that one user decided to leave today, what would it cost them? Lesson 5 follows the same "open one type at a time" pattern with dataMoat and scaleEconomies.

An everyday analogy: switching banks with ten direct debits

Switching banks, on paper, is trivial: you fill out a form, in a couple of days you have a new account. And yet, almost nobody does it, even when the new bank offers better terms. The reason has nothing to do with opening the new account — it has to do with untangling your life from the old bank: the automatic rent payment, the gym's direct debit, the streaming subscription, the car insurance, the paycheck your employer has been depositing there for three years. Switching means updating each one of those ten things, one by one, and if you forget even one, the result is a bounced payment, a late fee, a cut-off service. The new bank doesn't retain you with anything — you're held back by the work of disconnecting ten threads that you yourself, over time, tied to the old bank.

Now compare that to a bank that offers you a better rate in exchange for signing a one-year commitment contract, with a penalty if you leave early. It feels similar —in both cases "leaving costs something"— but they're two completely different things. The ten threads are a cost you built, with nobody forcing you, simply by using the service over time — and that's why they never disappear on their own. The contract is a fence the bank built and made you sign — and the day the contract expires, the fence disappears completely, even if the ten threads of your real life were never touched. That difference —threads you wove yourself, versus a fence imposed on you— is exactly what separates the three depth levels the model measures.

Worked example: three depths, three Mercado sellers

We reuse moatScore unchanged and run it on three of Mercado's real switching costs, one for each depth the model recognizes. sellerAnnualContract is a seller who signed a twelve-month exclusivity contract with Mercado, with a penalty if they leave early — depth contractual. buyerSavedPreferences is a buyer with saved payment methods, shipping addresses, a wishlist, and recommendations already calibrated to their history — depth habit: nothing stops them, but redoing all that on another platform feels like a hassle. sellerDashboardWorkflow is a seller who runs their entire daily operation through Mercado's dashboard: syncing inventory, processing orders, exporting accounting — depth dataAndWorkflow: leaving isn't "signing up somewhere else," it's rewiring their whole business.

// Pedagogical model: scores the DURABILITY (0-10) of a competitive advantage.
// Reused unchanged from lesson 2 -- this lesson digs into the three
// 'depth' levels of the switchingCost type.
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: 'sellerAnnualContract', type: 'switchingCost', depth: 'contractual' },
  { name: 'buyerSavedPreferences', type: 'switchingCost', depth: 'habit' },
  { name: 'sellerDashboardWorkflow', type: 'switchingCost', depth: 'dataAndWorkflow' },
];

console.log('=== Three switching-cost depths, same question: how expensive is it to leave? ===\n');
console.table(candidates.map(moatScore));

What to expect. Running the file with Node produces exactly this output:

=== Three switching-cost depths, same question: how expensive is it to leave? ===

┌─────────┬───────────────────────────┬─────────────────┬────────────┬──────────────┬───────────────────────────────────────────────────┐
│ (index) │           name            │      type       │ durability │   verdict    │                     rationale                     │
├─────────┼───────────────────────────┼─────────────────┼────────────┼──────────────┼───────────────────────────────────────────────────┤
│    0    │  'sellerAnnualContract'   │ 'switchingCost' │     3      │ 'not-a-moat' │   "switching cost of depth 'contractual'"          │
│    1    │  'buyerSavedPreferences'  │ 'switchingCost' │     5      │ 'weak-moat'  │      "switching cost of depth 'habit'"             │
│    2    │ 'sellerDashboardWorkflow' │ 'switchingCost' │     8      │    'moat'    │ "switching cost of depth 'dataAndWorkflow'"        │
└─────────┴───────────────────────────┴─────────────────┴────────────┴──────────────┴───────────────────────────────────────────────────┘

Notice the result that surprises anyone seeing this for the first time: sellerAnnualContract —a signed contract, with a legal penalty if the seller leaves early, the kind of thing that in a meeting would sound like "we've got them locked in"— gets durability: 3 and 'not-a-moat'. It doesn't even reach the 'weak-moat' threshold (4). The contract feels like the strongest switching cost of the three, because it's explicit, signed, legal — but the model scores it as the weakest, and the reason is in the analogy: a contract is a fence Mercado built, not a thread the seller wove by using the product. The day the contract expires, the fence disappears completely — and if during that year Mercado never gave the seller any real reason to stay (the operational dashboard from sellerDashboardWorkflow, for example), they'll most likely leave the moment they can, with more resentment than loyalty for having been tied down against their will.

Deep dive: earned vs. imposed — the switching cost you earn, and the one you impose

This lesson's central distinction isn't just "how much does it hurt to leave" — it's where that pain comes from. A dataAndWorkflow switching cost is earned: it exists because Mercado gave the seller so much real value —tools they genuinely use every day, that they spent time configuring— that disconnecting costs something, and that cost is an honest byproduct of having been useful. A contractual switching cost is, instead, imposed: it exists because Mercado wrote a clause, not because the seller built anything on top of the product. The difference matters for two practical reasons, not just philosophical ones.

The first: imposed switching costs have an expiration date and, almost always, a bad reputation — some jurisdictions legally limit how long an exclusivity clause can last, and a seller who feels "trapped" by contract, not by value, is a seller who badmouths the platform while waiting for the contract to end. The second, more uncomfortable for any team that relies too heavily on this type: a strong switching cost —especially the imposed kind— can turn into a moral hazard. If the team knows the seller can't leave this year, the temptation to stop investing in improving their experience —"they can't leave anyway"— is real, and that complacency is exactly what a seller trapped by contract, not by value, will remember the day the contract expires. An earned moat, dataAndWorkflow, doesn't carry that risk: if Mercado stops investing in the seller's dashboard, the switching cost erodes on its own, over time, because it stops delivering the value that sustained it — the incentive to keep investing is built into the moat's mechanics themselves, no contract is needed to force it.

Common mistakes

Relying on the contract as if it were the strongest advantage. What happens: the sales team negotiates twelve-month exclusivity contracts with the biggest sellers and reports it as "our moat with key accounts," without building anything additional that makes those sellers want to stay once the contract ends. Why it happens: a signed contract feels concrete and measurable —there's a date, a clause, a signature—, while a dataAndWorkflow switching cost is built gradually and is harder to point to on a slide. How to spot it: ask "what's left for this seller the day after the contract expires, besides the memory of having been tied down?" — if the answer is "nothing," the real durability is 3, not what the contract says. How to fix it: use the contract, if anything, as a temporary bridge while the real switching cost —deep integration, indispensable tools— gets built, never as the moat itself.

Confusing habit with permanent lock-in. What happens: the team observes that buyers "have always used Mercado" and concludes that habit is a solid moat, without testing how easily a competitor with a real incentive —an aggressive discount, a well-targeted campaign— could break that habit. Why it happens: habit feels stable because it requires no active effort from Mercado to sustain day to day, and that apparent stability gets confused with real durability. How to spot it: habit scores 5, barely above the 'weak-moat' threshold — if the team is treating it as a full 'moat' (≥7) in its decisions, there's active overestimation happening. How to fix it: treat any habit-type switching cost as a real but fragile advantage against a sufficiently large incentive — and look to deepen it toward dataAndWorkflow (lesson 7's exact topic) instead of settling for inertia.

Not investing in deepening an integration that already exists. What happens: Mercado already has sellers using the operational dashboard daily —the basis of a dataAndWorkflow switching cost—, but the product team doesn't prioritize the features that would deepen that integration —accounting export, automatic inventory sync with the seller's physical point of sale—, leaving the moat half-built at the habit level. Why it happens: deepening an existing integration doesn't feel as urgent as launching a new, visible feature, even though its impact on durability is much greater. How to spot it: if the roadmap constantly prioritizes new features over deepening the tools the biggest sellers already use every day, the opportunity to move from habit to dataAndWorkflow is being passed up. How to fix it: lesson 7 formalizes this — the depth of an integration is, literally, an architecture decision the engineering team controls, and moving it from habit to dataAndWorkflow changes durability from 5 to 8.

Exercises

Exercise 1 — Classify the depth. For each situation, decide whether the switching cost is contractual, habit, or dataAndWorkflow, and justify it in one sentence: (a) a buyer has their clothing size and favorite brands saved, calibrated over months of purchases; (b) a seller automatically exports a weekly sales report from Mercado directly into their accounting system; (c) a seller signed that they won't sell on any other platform for six months, in exchange for a lower commission.

See solution
  • (a) habit. It's useful information, accumulated over time, that saves the buyer effort — but it isn't integrated with any external system of the buyer's, and redoing it on another platform is tedious, not structurally costly.
  • (b) dataAndWorkflow. The automatic report is connected to a real external system (the seller's accounting) — disconnecting from Mercado breaks an operational process the seller depends on to run their business, not just a saved preference.
  • (c) contractual. It's an imposed clause with an expiration date, not a thread woven by using the product — the day the contract ends, the seller can leave with no additional structural cost.

Exercise 2 — Predict before running it. Without running code, using this lesson's switchingCost formula (depthScore = { contractual: 3, habit: 5, dataAndWorkflow: 8 }), predict the durability and verdict of this advantage: { name: 'unknownIntegration', type: 'switchingCost', depth: 'apiOnly' } — note that 'apiOnly' isn't any of the three keys of the depthScore object. Then verify by running moatScore on that object.

See solution

depthScore['apiOnly'] doesn't exist in the object, so the formula's ?? operator (depthScore[depth] ?? 3) falls back to the default value: durability = 3, the same level as contractual, with verdict: 'not-a-moat'. This isn't a code accident — it's a design decision of the model: any switching-cost depth that can't be explicitly classified into one of the three recognized categories is treated, by default, as the weakest one. The practical lesson: if you can't precisely name what type of switching cost you have, it's probably no stronger than a contract — and moatScore reminds you with the same number.

Exercise 3 — The contract's moral hazard. Describe, in two or three sentences, a hypothetical scenario where a Mercado team, confident that a seller is locked in by a one-year contract, stops investing in improving their experience on the seller dashboard. Explain, using this lesson's "deep dive" vocabulary, what happens to that seller's real durability the day the contract ends.

See solution

There's no single correct answer — the exercise evaluates the reasoning. A reasonable example: the product team, seeing that their twenty biggest sellers have a one-year exclusivity contract, decides to prioritize other features and postpones for months the operational dashboard improvements those same sellers had been requesting. During the contract year, durability on paper stays at 3 (the contract), but the seller never built any additional habit or dataAndWorkflow thread with the platform — their real relationship with Mercado never deepened. The day the contract expires, there's no layer underneath holding it up: durability falls to what it always was, zero real switching cost, and the seller —who also spent a year feeling tied down, not courted— has an extra reason to leave with the first competitor who offers them something better.

Summary and next step

In this lesson you opened the second moat type: switching cost, the friction of leaving, not the difficulty of arriving. You saw the three depth levels the model recognizes —contractual, the weakest because it's imposed and expires; habit, moderate because it's real but breaks with a sufficient incentive; dataAndWorkflow, the strongest because the user wove that thread themselves, by using the product over time— and why that hierarchy, counterintuitive at first glance, has solid logic behind it: earned beats imposed.

Before moving on you should be able to: classify any new switching cost into one of the three depths, explain why a signed contract scores lower than a usage habit, and name the moral hazard of relying too much on an imposed switching cost.

Lesson 5 opens the two remaining types before reaching the model's control group: data moats —which only count if they feed back into the product— and scale moats — where bigger, genuinely, can mean cheaper.

Resources

  • Hamilton Helmer, 7 Powers: The Foundations of Business Strategy7powers.com. "Switching costs" is, literally, one of the book's seven sources of power — the same distinction between an earned advantage and an imposed one that this lesson developed with the contract example. In English.
  • Investopedia, "Economic Moat" — investopedia.com/terms/e/economicmoat.asp. Switching costs are among the economic moat types Morningstar uses to rate companies — the same taxonomy, under different vocabulary, that the whole module is covering type by type. In English.