MVPGENERALSCALE-SPECIFICILLUSTRATIVE

Growing From the MVP

V1 shipped and something was learned. The next version is not "V1 plus the phase-2 list"; it is the smallest change that acts on what was learned, with each simplification undone only when its trigger fires.

The moveWorked exampleNext questions

The situation, the reflex, and why it stalls

Every lesson starts where being stuck starts: someone has a problem, and the first move that comes to mind feels like progress.

The question

V1 is in front of real users. How do I decide what the next version is, and how do I keep it from becoming the full feature list I refused to build the first time?

The situation

The store is live. A few dozen orders came through, a founder is delighted, and the "not V1" list has been re-titled "V2". I have a week of feedback and a feeling that I am about to build everything I declined to build before, in the same order as before, for the same reasons as before.

The reflex

Start on the phase-2 list. It was agreed, it is written down, and the MVP "worked", so the plan continues. It feels like the reward for having been disciplined.

Why it stalls

The list was written before anyone had seen a customer, and nothing from the customers has touched it. The feedback said checkout confused people on mobile and nobody used the filter; the list says coupons and recommendations. The plan continues as if V1 had taught nothing.

What the reflex produces — and fails to produce
  • The list was written before anyone had seen a customer, and nothing from the customers has touched it. The feedback said checkout confused people on mobile and nobody used the filter; the list says coupons and recommendations. The plan continues as if V1 had taught nothing.
  • Simplifications are undone all at once. Multi-currency, multi-warehouse and search all arrive in V2 because they were all deferred, though only one trigger fired. Each undoing is a migration, and three migrations at once is where the store's first serious outage lives.
  • The architecture "grows up" on schedule rather than on evidence. Someone proposes that V2 is the time to split into services and add a queue, because V1 was "just the MVP". No reading justifies either; the store has a few dozen orders.
ProblemUnderstandRequirementsConstraintsUnknownsDecompositionSmallest StepModelExperimentObserveDebugLearnIterate

The move

Precisely enough to apply it to a problem you have never seen — not a slogan.

  • Write down what V1 taught, as observations. "Orders happened, so people buy." "Half of the checkouts abandoned at the address step." "Nobody used filter-by-name." "The founder asked about a second warehouse." Each observation is evidence, and the next version is the smallest change that acts on the evidence — not the list.
  • Check the triggers on the "not V1" list against the observations. A trigger that fired ("a second warehouse exists") promotes its item; a trigger that did not ("catalog too big to filter") leaves its item where it was, however senior the person who wanted it. This is what makes "iterate" mean something: an iteration that ignores what was observed is not one.
  • Undo one simplification at a time, and undo the data shape first. Adding a warehouse column and backfilling the existing one is a small, boring migration; adding it during the multi-currency migration is not. Each undone simplification has an assumption it removes, and the removal is a change to find, not a feature to add (When Assumptions Change).
  • Treat architecture as a simplification with a trigger, like every other. The single process stays until a reading says it is the bottleneck; a queue arrives when something must happen after the response and cannot fail silently, not when the version number changes (Add Complexity Only When Required).

The loop after a release

The reflex goes from release straight to the list. The loop below puts three steps between them, and each has a way of failing that looks like doing it.

  1. 1
    Observe

    Write what users did, failed to do, asked for, and what broke — as observations, without conclusions.

    fails by Writing conclusions ("we need search") and calling them observations.

  2. 2
    Check triggers

    For each "not V1" item, did its trigger fire? Cite the observation.

    fails by Promoting an item because its owner is senior, not because its trigger fired.

  3. 3
    Choose the smallest change

    The smallest change that acts on the strongest observation — often a fix to the path.

    fails by Reading one observation as a mandate for a large feature.

  4. 4
    Undo one simplification

    Find the assumption comment; change the data shape in its own migration; then build on it.

    fails by Undoing three at once because they were all deferred together.

  5. 5
    Release and return

    Ship, and start again at Observe.

    fails by Skipping Observe on the second lap because the list is now "the roadmap".

One order for the next version, and the other

Given the observations, one sequence: repair the path first, then undo the simplification whose trigger fired, then re-examine. The alternative puts the migration first and is right when the data change is the risky part.

The store after V1
  1. 1
    Fix the mobile address form

    because The strongest observation is abandonment on the path; a leak in the path costs more than any feature adds.

  2. 2
    Warehouse table and `warehouse_id` on stock, backfilled

    because The multi-warehouse trigger fired; the data shape changes in its own boring migration, with no routing logic yet.

  3. 3
    Basket-size and conversion report from existing orders

    because It costs almost nothing, and it is the observation the coupon and recommendation triggers are waiting for.

  4. 4
    Return to Observe

    because Three changes are enough to learn from; the list is re-checked, not continued.

a different valid order Migration first: if the second warehouse is already receiving stock, the data shape is the urgent risk — a stock number that silently merges two locations is a correctness problem, not a feature gap — and the form fix follows. Choose this when the fired trigger threatens an untouchable rather than a conversion rate.

Scoring the proposal to "grow up" the architecture

The matrix compares three responses to "V2 is when we add the queue and split services", scored across the standard axes for a store at a few dozen orders. The point of the matrix is the caveat under it, not the numbers.

Trade-offs
OptionSimplicityReliabilityCostTimeMaintainabilityNote
Stay single-process; write the triggerNothing changes; a sentence says what reading would change it.
Add a queue for confirmation email onlyJustified only if email must not block or be lost — is that observed?
Split into services nowEvery boundary becomes a network call with no reading that asked for it.

caveat These are rankings at a few dozen orders, not measurements; at a load where the database is saturated the "stay" row loses its reliability score and the queue row gains one. The numbers change with the readings, which is the argument for having readings before having numbers.

How to do it

Most important first.

  • Before touching the list, write the observations from V1 in one place: what users did, what they failed to do, what they asked for, what broke (The Engineering Notebook).
  • Walk the "not V1" list and mark each trigger fired or not fired, with the observation that says so.
  • Choose the next version as the smallest change that acts on the strongest observation — often a fix to the path, not a new feature.
  • For each simplification you undo, find the assumption comment you left, and change the data shape in its own migration before building the feature on it (What Is Not V1).
  • For any proposed component, ask the complexity ledger questions — what it solves, what it introduces, what happens when it fails — and require a reading, not a version number, as the answer to the first (The Complexity Ledger).

Worked on a concrete problem

The move has to produce something. This is what it produced.

  • Observations after V1: people bought (the claim holds); many abandoned at the address form on phones; filter-by-name was rarely used; the founder mentioned a second fulfilment location. Triggers: multi-warehouse fired; search did not; coupons did not (there is now a baseline, but nothing suggests price is the problem). Next version: fix the address form, then the warehouse migration. Not next: coupons, search, recommendations, services.
  • Undoing "one warehouse": a warehouses table, a warehouse_id on stock, existing stock backfilled to the one location, the CHECK (stock >= 0) kept per row. No picking logic yet — the trigger was "a second location exists", not "we need to route orders". That is a later trigger with a later observation.
  • The architecture proposal, answered with readings: a few dozen orders, database mostly idle, checkout latency dominated by the provider round-trip. Nothing is a bottleneck. The queue is declined, with the trigger written: "when order confirmation email must not block checkout and must not be lost".

How you know it worked

What now exists that did not before, and what question you can now ask.

  • The next version is named by an observation ("mobile abandonment"), not by a list position ("phase 2").
  • Each undone simplification is its own migration, and you can say which trigger fired for it.
  • Some deferred items were deferred again, with the trigger that still has not fired.
  • The architecture is unchanged, and there is a sentence saying what reading would change it.

The questions you can now ask

The field this whole domain exists for. After this lesson, these are the questions to put to an unfamiliar problem.

Next questions
  • ?What did V1 actually teach, stated as observations rather than conclusions?
  • ?Which triggers on the "not V1" list fired, and which did not — and what am I about to build anyway?
  • ?What is the smallest change that acts on the strongest observation?
  • ?Which simplification am I undoing, where is the assumption it removes, and can it be its own migration?
  • ?What reading would justify the component someone is proposing, and do I have it?

What can go wrong

How the move itself fails
  • Observations are collected and then overruled by the list anyway, because the list was promised. The list was a set of triggers; if it was a promise, the promise was the mistake.
  • One observation is read as a mandate for a large feature. "Nobody used filter" could mean search is needed, or that products were found from the home page and filter was unnecessary. An observation is evidence for a question, not for a build.
  • The smallest change is always the smallest, forever, and the product never grows past the path. At some point the claim is proven and the next claim — "people will come back" — needs its own MVP; the move restarts one level up (MVP Thinking).
What the move costs
  • Acting on observations means the roadmap changes after every release, and people who planned around it have to re-plan.
  • One migration at a time is slower in calendar terms than one big V2 migration, and safer in every other term.
  • Declining architecture on evidence means being the person who says no to the exciting proposal, repeatedly, with numbers.
Misreads
  • "V2 is V1 plus the deferred features." V2 is V1 plus what V1 taught. Some deferred features come in; some are deferred again; some are deleted.
  • "Undoing a simplification is a feature." It is a change to a data shape with a feature waiting behind it; separating the two is what keeps the migration boring.
  • "Now we have users, we can scale." Now you have readings. Scale is what the readings say, and a few dozen orders say nothing.

Where this applies

Problem-solving advice is stated as universal far more often than it is. These labels say what each method is specific to — and where CONTESTED appears, the note gives the strongest form of the opposing view.

  • GENERALObserve, check triggers, smallest change, one undoing at a time — this is the iteration loop for any product after any release, not only after the first.
  • SCALE-SPECIFICAt a few dozen orders no reading justifies a component and the move is mostly about scope. At real load the readings start to say things, and the same move starts promoting architecture items — the loop is the same; the evidence differs.
  • ILLUSTRATIVEThe dozens of orders, the abandonment at the address form and the second warehouse are invented to show the shape of the move.

Where the depth lives

This domain asks the question and hands the answer off by name.