AI EngineeringZero to ProductionHome·About·What’s new·Contact
Part V · Chapter 7

The Forward Deployed Engineer Method

Chapters 1–6 taught you to build LLM systems. This one teaches you to deploy them the way a Forward Deployed Engineer does: embed with a real user, find the problem worth solving, ship a thin slice, and expand only as you earn trust. It's the difference between a demo and a system someone depends on.

⏱️ ~1.5 hours🧪 1 labs🎯 Beginner→Tech-lead

Learning objectives

  • Explain the Forward Deployed Engineer (FDE) method.
  • Work backward from a customer outcome, not a feature list.
  • Ship a thin end-to-end slice fast, then iterate with the user.
  • Scale the FDE approach across a team.
▶ Runnable companionEvery code block in this lesson is also a standalone file under code/ch07-fde/ in the course, with a README on how to run it. Read here, run there — no need to copy-paste.

1 · What an FDE does essential

Picture the demo that dazzled the room and then died. You spent three weeks building something clever — a slick agent, a beautiful RAG pipeline — it wowed everyone in the review, and six weeks later nobody uses it. Not because the code was bad. Because it solved a problem the users didn't actually have, in a shape that didn't fit how they work. That gap — between "technically impressive" and "someone depends on this daily" — is the single most expensive gap in software, and it's the one the Forward Deployed Engineer method exists to close.

Here's the mental image that makes it click. A normal engineer is like an architect who mails blueprints to a construction site and hopes for the best. An FDE is the architect who moves into the half-built house, lives there while the walls go up, notices that the kitchen is in the wrong place before the plumbing is set, and fixes it on the spot. The difference isn't talent — it's proximity. When you're in the room where the software is actually used, you learn the real problem in hours instead of guessing at it for a quarter.

The name unpacks the whole idea. Forward means deployed toward the customer, at the front line, not back at HQ behind a Jira board. Deployed means you go to them — their office, their Slack, their messy real data — rather than waiting for a tidy spec to arrive. Engineer means you still ship real, working software; you are not a consultant writing recommendations. The role fuses three jobs that companies usually keep separate: the discovery of a product manager, the empathy of a support rep, and the delivery of a senior engineer.

The common mistake — and it snares strong engineers hardest — is treating "understand the customer" as someone else's job. You take the ticket, build exactly what it says, and hand it back. But the ticket is a guess the customer made about what they needed, translated through a PM, filed weeks ago. The FDE's superpower is refusing to trust that translation: you sit with the actual human, watch them work, and discover that the "report export feature" they asked for is really a plea to stop spending Friday afternoons copying numbers into a spreadsheet. Same request, completely different — and far simpler — solution.

So the precise definition: the Forward Deployed Engineer method is about building the right thing with the customer in the room. An FDE embeds with users, learns the real problem, and ships working software against it — closing the gap between what's technically possible and what actually helps. Chapters 1–6 taught you to build; this chapter teaches you to point that skill at the problem that's genuinely worth solving.

normal engineer — back at HQ HQ / Jira gets a ticket Builds the spec hopes it fits Demo dies solved the wrong problem FDE — embedded with the user In the room watches real work Discovery · empathy · delivery, fused Working software someone depends on Proximity is the whole trick. The normal engineer builds a ticket at arm's length and the demo dies; the FDE embeds with the user, fuses PM discovery, support empathy and senior delivery, and ships software someone actually depends on.
🗺️ How to read this diagram

Read it as two lanes stacked top and bottom, each flowing left to right — the same engineer, two very different distances from the customer.

  • The top grey row is the arm's-length path: a ticket from HQ → build exactly what the spec says → the red box, where the demo dies because it solved a problem the user didn't have.
  • The bottom green/blue row is the FDE path: being in the room watching real work, which lets one person fuse the three usually-separate jobs — a PM's discovery, a support rep's empathy, a senior engineer's delivery.
  • The payoff box on the bottom right is the difference proximity buys: working software someone depends on, not an impressive demo nobody uses.

In short: Same skill, different distance. Back at HQ you build the ticket; in the room you discover the real problem and ship the thing that helps.

2 · Work backward from the outcome essential

Try this uncomfortable experiment on your last project. Ask: if this feature shipped perfectly and nobody's day got measurably better, would we have wasted the quarter? For most feature-driven work the honest answer is yes — and that's the trap. We fall in love with what the technology can do and forget to ask what the human on the other end actually needed to be different by Friday. Working backward from the outcome is the discipline that keeps you from building a magnificent bridge to nowhere.

The analogy is a GPS. You don't tell a GPS "take three left turns and a highway" — you tell it the destination, and it works backward to the shortest route from where you stand. Feature-first thinking is picking turns and hoping they add up to somewhere useful. Outcome-first thinking is naming the destination — "incident triage drops from 45 minutes to 5" — and then letting that pin down the smallest route that gets there. The destination is fixed and concrete; the route is negotiable and, crucially, usually much shorter than you'd have guessed.

Why this matters so much for LLM work specifically: language models are seductively capable. They can summarize, classify, translate, draft, extract, reason — so "what can the LLM do?" returns an intoxicating list, and you can burn a month building five of those things before noticing none of them moved the customer's needle. Starting from the outcome inverts the question from "what's possible?" to "what's necessary?" — and necessary is almost always a tiny subset of possible. The outcome is a scope-cutting knife.

The common mistake is a fake outcome dressed as a real one. "Users want an AI assistant" is not an outcome — it's a feature with a bow on it. A real outcome names who, what changes for them, and ideally by how much: "an on-call engineer diagnoses a paging alert in 5 minutes instead of 45." Notice that a true outcome contains no technology at all — no "LLM," no "RAG," no "agent." If your stated outcome mentions the tool, you've smuggled the solution into the problem and quietly stopped working backward. The test in Exercise 2 encodes exactly this: a plan with no named customer outcome is rejected before anyone scores its scope.

So the rule, stated plainly: don't start from "what can the LLM do?" Start from the customer's outcome — the decision they need to make, the hours they want back — and work backward to the smallest system that delivers it. Features are a means; the outcome is the point. The diagram below turns this into the loop you'll run on every FDE engagement.

Customer outcome hours saved Smallest slice end-to-end Ship + watch in production Iterate with user tight loop
🗺️ How to read this diagram

This is the whole FDE method in one picture — a loop, read left to right, that you keep running with a real customer instead of guessing behind a spec. Each box feeds the next.

  • Customer outcome (hours saved) — start here, not with a feature list. Name the result the customer actually wants (a decision made, hours given back). Everything else serves this.
  • Smallest slice (end-to-end) — the arrow means "work backward to": pick the tiniest thing that delivers that outcome, but works the whole way through, from input to result.
  • Ship + watch (in production) — you put that slice in front of the real user and observe how they actually use it, where it breaks, what they ask for next.
  • Iterate with user (tight loop) — you turn what you watched into the next slice. The shorter this loop, the faster you learn — that closeness to the user is the FDE's real edge.

In short: It's a cycle, not a straight line: outcome → smallest slice → ship & watch → iterate, then back to a sharper slice. The point is learning fast, not shipping big.

3 · Intermediate — the thin end-to-end slice intermediate

Two teams get the same project on a Monday. Team A spends six weeks building a gorgeous, fully-featured module — perfect error handling, every edge case, a config system for options nobody asked for — and demos it in week seven. Team B ships something rough but complete in week one: it takes real input, runs all the way through, and hands the user a real (if ugly) result. By the time Team A demos, Team B has already learned three things their users actually wanted and thrown away one thing they thought mattered but didn't. Team B wins, and it isn't close. The thin end-to-end slice is why.

Here's the picture. Think of the system you're building as a cake with layers — UI, logic, model call, data, storage. A "thin vertical slice" cuts a narrow wedge through all the layers: a little bit of every layer, wired together, working for exactly one real case. The tempting alternative is to build one whole layer beautifully — frost the entire top of the cake — before touching the layers beneath. But a perfect layer of frosting on no cake feeds nobody. A thin wedge, top to bottom, is something a real person can actually take a bite of and tell you how it tastes.

Why "end-to-end" is the load-bearing word, not "small": smallness alone isn't the point — a tiny, polished, isolated component is still useless to the user. What earns feedback is reaching the whole way through to a result the user can react to. That's exactly why the lab's slice_score penalizes "not end-to-end" with 3 risk points while scope and speed only cost 2 each — a slice that doesn't connect input to real output leaves you flying blind, and no amount of internal polish buys back the feedback you lost.

The common mistake is the "I'll just finish this part properly first" instinct — and it feels like professionalism, which is what makes it dangerous. You tell yourself you'll build the retrieval layer solidly, then wire up the agent, then the UI, and only show the user at the end. But every week you spend perfecting a layer in isolation is a week of building on unverified assumptions. The slice inverts the order: get something crude working through every layer first, put it in front of the user, and let their reaction tell you which layer actually deserves the polish. You'll routinely find the part you were about to gold-plate didn't matter at all.

So the principle: ship a thin vertical slice that works end-to-end for one real case — not a polished module in isolation. A rough pipeline the user can actually run beats a perfect component they can't, because it produces the feedback that tells you what to build next. The lab below turns this judgment into a scorer you can run on any plan before you write a line of the real thing.

one polished layer UI Logic Model call Data Storage — built alone reaches no user → no feedback thin vertical slice UI Logic Model call Data Storage one real case, end-to-end rough but complete beats polished but disconnected Cut down, not across. A flawless single layer (left) feeds nobody; a narrow wedge through every layer (right, green) delivers one real case a user can react to — and that reaction is the feedback that tells you what to build next.
🗺️ How to read this diagram

Picture the system as a stack of layers — UI on top, storage at the bottom. The two sides show the two ways to spend your first week.

  • The left stack fills one whole layer beautifully (the red 'storage' band) while the rest sit untouched. Perfect, but horizontal — it never connects up to a user, so it earns no feedback.
  • The right stack is the thin vertical slice: the green sliver cuts down through every layer at once — a little UI, a little logic, a model call, data, storage — wired together for exactly one real case.
  • The colors are the verdict: red = disconnected and feedback-blind; green = end-to-end and usable. The green wedge is narrow on purpose — small isn't the point, reaching all the way through is.

In short: Build a wedge top-to-bottom, not one perfect floor. Rough-but-complete lets a real person take a bite and tell you how it tastes.

Example code for learning — review, test, and adapt it before running against real or production systems. Commands can create, change, or delete resources. See the Terms & Disclaimer.
Python · score whether a plan is a thin slice or a big-bang build (runs)
slice.pydef slice_score(end_to_end, weeks_to_first_use, num_features):
    risk = 0
    risk += 0 if end_to_end else 3          # not end-to-end = flying blind
    risk += 0 if weeks_to_first_use <= 2 else 2
    risk += 0 if num_features <= 2 else 2    # scope creep
    if risk == 0: return "thin slice — ship it, then learn"
    if risk <= 3: return "trim scope — get to real use faster"
    return "big-bang risk — you'll build the wrong thing"

print(slice_score(end_to_end=True,  weeks_to_first_use=1, num_features=1))
print(slice_score(end_to_end=False, weeks_to_first_use=8, num_features=6))
thin slice — ship it, then learn
big-bang risk — you'll build the wrong thing
▶ How this works

This tiny program is a gut-check scorer: describe a plan and it tells you whether it's a safe "thin slice" or a risky "big-bang build". It turns the chapter's advice into a rule you can run. The idea: add up risk points for the three things that most often sink a project, then read the total.

  1. def slice_score(end_to_end, weeks_to_first_use, num_features): takes three facts about your plan: does it work all the way through, how many weeks until a real person uses it, and how many features you're building first.
  2. risk = 0 starts a running score, then each line adds points for a warning sign. risk += 0 if end_to_end else 3 reads as: "add 0 if it's end-to-end, otherwise add 3." Not being end-to-end is the biggest penalty — the comment calls it flying blind.
  3. The next two lines add 2 points each if it takes more than 2 weeks to first use, or if you're packing in more than 2 features (that's scope creep). Small and soon scores low; big and slow scores high.
  4. The if ladder reads the total: 0 means a clean thin slice, <= 3 means trim scope and get to real use faster, and anything higher is flagged as big-bang risk — you'll likely build the wrong thing.
  5. The two print(...) lines run the scorer on a good plan and a bad one so you can see both verdicts.

What the output means: Two lines print. The first plan (end-to-end, 1 week, 1 feature) scores 0 → "thin slice — ship it, then learn". The second (not end-to-end, 8 weeks, 6 features) scores the maximum → "big-bang risk — you'll build the wrong thing".

Try this: Change the second call to weeks_to_first_use=2, num_features=2 but keep end_to_end=False. It still adds 3 for not being end-to-end, so it lands on "trim scope" — proof that shipping something that works end-to-end matters most.

4 · Advanced — iterate in the feedback loop advanced

Shipping the slice isn't the finish line — it's the starting gun. The most common way a promising FDE project quietly dies is that the slice goes live, everyone claps, and then the team drifts back to building whatever was next on the roadmap. The whole reason you shipped something rough and fast was to earn feedback; walking away the moment it's live is like planting a seed and never coming back to water it. The value was never in the slice. It's in the loop the slice unlocks.

The analogy is a chef who actually eats in their own dining room. A bad chef sends the plate out and never leaves the kitchen. A great one sits at a table, watches which dishes come back half-eaten, notices the diner reaching for more salt, and hears the offhand "this is lovely but I'm in a hurry." Every one of those signals is a next-slice waiting to be built — and none of them are visible from the kitchen. The FDE's edge, as the tip below says, isn't better code; it's a shorter distance between building something and finding out whether it helped.

But watching alone has a failure mode, and it's a sneaky one: you'll feel like each version is better whether or not it is. Humans are pattern-matchers who see improvement in noise — three good sessions in a row feel like progress even when they're a coin flip landing heads. This is exactly where the evaluation discipline from Chapter 5 stops being academic. You instrument the slice so "it's better now" is a measured success rate over enough real sessions, not a warm feeling from a demo that happened to go well. Exercise 4 makes the trap concrete: the same 25-point jump in success rate is a real win on a large sample and pure noise on a tiny one.

The common mistake is optimizing what's easy to measure instead of what the outcome needs. It's tempting to instrument latency and token cost — they're trivial to log — and call it a feedback loop. But if the customer's outcome was "diagnose the alert faster," the number that matters is did they diagnose the alert, not how many milliseconds the call took. Tie your instrumentation back to the outcome from Section 2, or you'll spend the loop making the wrong thing measurably better.

So: once the slice is in real use, the FDE lives in the feedback loop — watch how the user actually uses it, where it fails, what they ask for next, and turn that into the next slice. This is where evals (Ch 5) matter: you instrument the slice so "it's better now" is measured, not felt.

Ship the slice into real use Watch real use where it fails Measure success rate over sessions Build next slice only if delta is real a +25% jump is a win on 12 sessions, noise on 4 The loop is the product, not the slice. Ship → watch → measure → build the next slice, and keep cycling. The "measure" gate is what stops a lucky streak on a tiny sample from masquerading as improvement.
🗺️ How to read this diagram

Follow the arrows clockwise — it's a cycle, not a finish line. Shipping the slice starts the loop; it never ends it.

  • Ship the slice (top) puts something rough in front of the real user — that's the starting gun, the moment feedback becomes possible.
  • Watch real use (right) is the FDE sitting in the dining room: seeing where it breaks and what the user reaches for next.
  • Measure success (green, left) is the honesty gate — a success rate over enough sessions, so "it feels better" becomes a number. The caption's line is the trap: the same +25% is a real win on 12 sessions but pure noise on 4.
  • Build next slice (bottom) turns a measured improvement into the next thing to ship, then the arrow loops back to the top.

In short: Ship → watch → measure → next slice, repeat. The shorter and more measured the loop, the faster you learn — and the less a coin-flip masquerades as progress.

Proximity to the user is the advantageThe FDE edge isn't better code — it's a shorter loop between building and learning what to build. Being in the room (or the same Slack) when your software fails is worth more than a month of guessing behind a spec.

5 · Professional — managing the pull to over-build professional

Here's the plot twist: the better an engineer you are, the more dangerous this section is for you. Over-building isn't a beginner's mistake — beginners ship crude things because crude is all they can manage. It's the experienced engineer, the one who can see the elegant general abstraction, who is most tempted to build it. You spot that today's specific solution could be a configurable framework serving ten future cases, and the craftsman in you aches to build the framework. That ache is the enemy, and naming it is half the battle.

The analogy is a road no one has walked yet. You could pave a magnificent eight-lane highway across the field — or you could watch where people actually wear a footpath into the grass, and pave that. Over-building is pouring concrete before anyone has walked anywhere: you're guessing the route, and you'll usually guess wrong, ending up with a beautiful highway that misses where people actually want to go. Ship the footpath first. Let real feet tell you where the road belongs, then pave the path they already chose. The generalization is earned by observed use, not designed up front.

Why the pull is so strong — and why it feels virtuous — is worth understanding. Building the general system feels like the responsible, senior, future-proof thing to do; shipping the narrow ugly one feels like technical debt you'll be judged for. But this is backwards. The narrow version that a real user depends on is proof; the general version built on speculation is debt with a nice paint job. You've committed to abstractions before you knew which ones the problem actually needs, and every wrong guess is now baked into an interface you have to maintain. Bespoke-and-proven beats general-and-speculative every time.

The common mistake, stated bluntly, is generalizing on taste instead of evidence. "I can tell this needs to be a platform" is taste. "Five distinct teams have used the bespoke version dozens of times over a month" is evidence. Feelings of readiness are exactly what the discipline exists to overrule — which is why Exercise 5 turns "may we generalize?" into a checkable gate with hard thresholds for distinct users, weeks in production, and real request volume. When the gate says stay bespoke, you stay bespoke, no matter how ready the abstraction feels.

So the hard part is discipline: resisting the urge to build the general, elegant system before you've proven the specific, ugly one solves the problem. Ship narrow, earn the right to generalize with evidence of real use. Over-building is the most common FDE failure — and, as you'll see next, the one a good lead builds guardrails against for the whole team.

Bespoke & narrow ugly, but proven Evidence gate ≥3 users · ≥2 wks · ≥25 uses Generalize the product thin evidence → stay bespoke Generalize only through the gate. The bespoke version earns the right to become a product by clearing hard thresholds — distinct users, weeks in production, real request volume. Feels-ready doesn't open the gate; evidence does.
🗺️ How to read this diagram

Read left to right, but notice the diamond in the middle is a checkpoint, not a box you pass automatically.

  • The green box on the left is what you ship first: the bespoke, narrow, even ugly version — its virtue is that a real user actually depends on it.
  • The amber diamond is the evidence gate. It doesn't ask how elegant your abstraction is; it checks hard numbers — enough distinct users, enough weeks in production, enough real requests (the ≥3 / ≥2 / ≥25 thresholds from Exercise 5's may_generalize).
  • Only when all three clear do you follow the arrow right to generalize the product. If evidence is thin, the down arrow sends you back to stay bespoke — no matter how ready the abstraction feels.

In short: Bespoke-and-proven earns the platform; general-and-speculative is debt with a paint job. The gate overrules taste with evidence.

6 · Tech-lead — scaling the method tech-lead

The uncomfortable truth about a great FDE: they don't scale. One brilliant engineer who instinctively works backward from outcomes, ships thin slices, and refuses to over-build is worth a fortune — and is also a single point of failure. The moment you have four teams and one of them is you, "just have good instincts" stops working. The tech-lead's job is to take what lives in one person's gut and turn it into something a whole organization does by default, even on a bad day, even the engineers who've never heard the word "FDE."

The analogy is the difference between a talented home cook and a restaurant chain. The home cook tastes as they go and it comes out perfect — but you can't open fifty locations on their tongue. A chain writes the recipe down, sets the oven temperature, builds the checklist, and puts a thermometer in the kitchen so quality survives being handed to people who aren't the founder. Scaling the FDE method is the same move: you convert the instinct into process and instrumentation so it doesn't evaporate the moment the one person who "gets it" is on vacation or busy on another team.

Concretely, the loop from this whole chapter — outcome → slice → measure → iterate — becomes the team's rails. Every project brief must name a customer outcome (Section 2's gate, made mandatory). Thin-slice-then-iterate is the default cadence, not a heroic exception. Instrumentation and evals (Section 4) are baked in from day one so "better" stays measured across every team. And the generalization gate (Section 5) governs the path to productize — you only invest in the general platform once a bespoke deployment has proven its value. Each rung of this chapter becomes one rail of the team's operating system.

The common mistake here is the opposite of over-building code — it's over-building process. A lead who's just discovered the method can smother teams in mandatory templates, approval gates, and adherence meetings until the ceremony costs more than the drift it prevents. The discipline is to make the practice visible and cheap, not heavy. That's why Exercise 6 builds a lightweight scorecard rather than a governance board: a five-check score per team turns "are we still doing FDE?" into a number a lead can glance at, flagging teams drifting back to big-bang builds without holding anyone hostage to process.

So a lead turns one FDE's instinct into a team practice: outcome-first framing in every project, thin-slice-then-iterate as the default, instrumentation baked in so learning is measured, and a path to productize what started as a bespoke deployment. The method scales when the loop (outcome → slice → measure → iterate) is the team's default, not one person's habit.

One FDE's gut instinct becomes 4 team rails (the chapter's rungs) Outcome-first brief — §2 gate, mandatory Thin-slice-then-iterate — default cadence Instrumentation & evals — §4, from day one Generalization gate — §5, path to productize glance-able per-team scorecard Instinct → rails. A lead converts one person's gut feel into four cheap, default rails — one per chapter rung — so the practice survives being handed to engineers who never heard the word "FDE", and a scorecard makes drift visible.
🗺️ How to read this diagram

Read left to right: the single green box on the left is the thing that doesn't scale; the four stacked bands on the right are what it must become.

  • The left green box is one brilliant FDE's instinct — worth a fortune, but a single point of failure the moment there are four teams.
  • The four blue bands are that instinct written down as rails, each tied to a section of this chapter: the outcome-first brief (§2), thin-slice-then-iterate as the default cadence, instrumentation and evals from day one (§4), and the generalization gate that guards the path to productize (§5).
  • The line at the bottom is the lead's cheap enforcement: a glance-able per-team scorecard (Exercise 6) that turns "are we still doing FDE?" into a number — visible without smothering teams in process.

In short: Each rung of the chapter becomes one rail of the team's operating system, and a lightweight scorecard flags any team drifting back to big-bang builds.

Bespoke first, product secondMany great products started as one FDE solving one customer's problem end-to-end, then generalizing what worked. A lead runs this deliberately: prove value bespoke, then invest in the product — not the reverse.

Exercise CH07.1 — Design a thin slice

Context: The whole method starts by working backward from a customer outcome, then cutting scope until the first slice is genuinely thin. Doing it once on a real problem is how the instinct sticks.

Your task: Take a real problem someone has: write the customer outcome in one sentence, design the thinnest end-to-end slice that delivers it, and score the plan — cutting scope until it reads as a thin slice.

Requirements:

  • State the customer outcome in a single sentence — not a feature list
  • Design a slice that is genuinely end-to-end (a real user can use it)
  • Score it with the slice-risk logic from the ladder
  • If it flags risk, trim scope and re-score until it reads "thin slice"
  • Keep first real use inside ~2 weeks and the slice to a couple of features

💡 Hint: If you can't name who uses the slice and what they get, the outcome isn't sharp enough yet — fix that before touching scope.

🪜 Practice ladder beginner → industry

Six graded exercises, easy to real-world. Try each before opening its solution.

Exercise 1 · Rebuild slice_score from the lessonBeginner

Context: The Forward Deployed Engineer's core instinct is shipping the thinnest end-to-end slice. The lesson turns that instinct into a number so a plan's risk is visible before anyone writes code.

Your task: Reimplement the lesson's slice_score and map the total risk to a verdict.

Requirements:

  • +3 risk if the slice is not end-to-end
  • +2 risk if first real use is more than 2 weeks out
  • +2 risk if it bundles more than 2 features
  • Map total to thin slice / trim scope / big-bang risk
  • Show a clean plan scoring 0 and a bloated plan scoring high

💡 Hint: Each risk factor is an independent additive penalty; sum them first, then classify the single total.

Show solution

The scorer encodes the FDE priorities: end-to-end matters most, then speed to real use, then scope.

def slice_score(end_to_end, weeks_to_first_use, num_features):
    risk = 0
    risk += 0 if end_to_end else 3
    risk += 0 if weeks_to_first_use <= 2 else 2
    risk += 0 if num_features <= 2 else 2
    if risk == 0:
        return "thin slice - ship it, then learn"
    if risk <= 3:
        return "trim scope - get to real use faster"
    return "big-bang risk - you'll build the wrong thing"

print(slice_score(True, 1, 1))   # thin slice - ship it, then learn
print(slice_score(False, 8, 6))  # big-bang risk - you'll build the wrong thing
Exercise 2 · Outcome-first framing + the slice check togetherIntermediate

Context: A plan that lists features but names no customer outcome is the chapter's classic anti-pattern. Validity requires both a stated outcome and a thin-slice score.

Your task: Write validate_plan that rejects a plan with no customer outcome, then falls through to the slice-scoring logic.

Requirements:

  • Read the plan's customer_outcome and reject if it is missing or blank
  • Only score the slice once the outcome gate passes
  • Reuse the same +3/+2/+2 risk factors from Exercise 1
  • Return a clear message: rejected, thin-slice OK, or trim-with-risk-N
  • Demonstrate both a rejected plan and an accepted thin slice

💡 Hint: Treat the outcome as a hard precondition — a short-circuit return before any scoring — not another additive penalty.

Show solution

Outcome-first is the gate before scope: a well-scoped slice aimed at no outcome is still the wrong thing built quickly.

def slice_score(end_to_end, weeks_to_first_use, num_features):
    risk = (0 if end_to_end else 3) + (0 if weeks_to_first_use <= 2 else 2) \
         + (0 if num_features <= 2 else 2)
    return risk

def validate_plan(plan):
    outcome = plan.get("customer_outcome", "").strip()
    if not outcome:
        return "REJECT - name the customer outcome first, not a feature list"
    risk = slice_score(plan["end_to_end"], plan["weeks_to_first_use"], plan["num_features"])
    if risk == 0:
        return f"OK - thin slice toward: {outcome}"
    return f"TRIM (risk {risk}) - slice toward: {outcome}"

print(validate_plan({"customer_outcome": "", "end_to_end": True,
                     "weeks_to_first_use": 1, "num_features": 1}))  # REJECT ...
print(validate_plan({"customer_outcome": "cut incident triage from 45min to 5min",
                     "end_to_end": True, "weeks_to_first_use": 1, "num_features": 1}))  # OK - thin slice ...
Exercise 3 · Rank candidate slices by value-per-riskAdvanced

Context: When several thin slices are viable, the FDE builds the one with the best return on risk — and knows that the safest slice is worthless if it delivers almost nothing.

Your task: Given candidate slices each with hours_saved_per_week and a slice risk, rank them and pick what to build first, discarding safe-but-pointless options.

Requirements:

  • Compute each slice's risk with the Exercise 1 scorer
  • Skip any candidate whose value falls below a minimum threshold
  • Rank by a value-per-risk ratio, highest first
  • Guard against divide-by-zero when risk is 0 (e.g. use risk + 1)
  • Show a high-risk slice and a too-cheap slice both dropped for the same reason: not worth building first

💡 Hint: A safe slice and a valuable slice can both be wrong first picks — the ratio is what reconciles them into one ordering.

Show solution

The FDE picks the thinnest slice that still moves the outcome — highest value per unit of risk, with a floor on value so 'safe but pointless' loses.

def slice_score(end_to_end, weeks, feats):
    return (0 if end_to_end else 3) + (0 if weeks <= 2 else 2) + (0 if feats <= 2 else 2)

def rank_slices(candidates, min_value=1.0):
    scored = []
    for c in candidates:
        risk = slice_score(c["end_to_end"], c["weeks"], c["feats"])
        if c["hours_saved_per_week"] < min_value:
            continue                     # too little value to bother, even at low risk
        value_per_risk = c["hours_saved_per_week"] / (risk + 1)  # +1 avoids div-by-zero
        scored.append((value_per_risk, c["name"], risk))
    scored.sort(reverse=True)
    return scored

cands = [
    {"name": "triage-diagnoser", "hours_saved_per_week": 8, "end_to_end": True, "weeks": 1, "feats": 1},
    {"name": "full-provisioner", "hours_saved_per_week": 20, "end_to_end": False, "weeks": 8, "feats": 6},
    {"name": "tidy-log-formatter", "hours_saved_per_week": 0.2, "end_to_end": True, "weeks": 1, "feats": 1},
]
for vpr, name, risk in rank_slices(cands):
    print(f"{name}: value/risk={vpr:.1f} (risk {risk})")
# triage-diagnoser wins; full-provisioner high value but high risk; formatter dropped (too little value)
Exercise 4 · Instrument the feedback loop so 'better' is measuredExpert

Context: The FDE instruments the slice so "it's better now" is a number, not a feeling — and small user samples make a lucky streak look like progress.

Your task: Given two rounds of pass/fail user sessions, decide whether the latest iteration is a real improvement or just within noise.

Requirements:

  • Compute a success rate from a list of session results
  • Require a minimum sample size before judging (small samples return "not enough sessions")
  • Require the delta to clear a minimum threshold before calling it real
  • Distinguish improvement, regression, and within-noise
  • Show that the same percentage jump is "real" on a large sample but "noise" on a tiny one

💡 Hint: Two gates protect you here: enough sessions to trust the rates at all, and a delta big enough to exceed the wobble of a small sample.

Show solution

With small samples, a raw rate jump can be noise; a simple absolute-margin rule tied to sample size keeps you honest about whether the loop actually improved things.

def success_rate(sessions):
    return sum(1 for s in sessions if s["success"]) / len(sessions)

def is_real_improvement(before, after, min_delta=0.10, min_n=10):
    if len(before) < min_n or len(after) < min_n:
        return False, "not enough sessions to conclude - keep watching"
    delta = success_rate(after) - success_rate(before)
    if delta >= min_delta:
        return True, f"real improvement: +{delta:.0%}"
    if delta <= -min_delta:
        return False, f"regressed: {delta:.0%}"
    return False, f"within noise ({delta:+.0%}) - not proven"

before = [{"success": i < 6} for i in range(12)]   # 6/12 = 50%
after  = [{"success": i < 9} for i in range(12)]   # 9/12 = 75%
print(is_real_improvement(before, after))  # (True, 'real improvement: +25%')
print(is_real_improvement(before[:4], after[:4]))  # (False, 'not enough sessions ...')
Exercise 5 · A review gate that resists over-buildingProfessional

Context: Over-building is the chapter's number-one failure. A team needs a lightweight gate so the general, abstracted version is only approved once there is evidence of real use.

Your task: Encode a may_generalize gate that approves building the general version only when usage evidence clears thresholds for distinct users, weeks in production, and real requests.

Requirements:

  • Check distinct users, weeks in production, and real request volume against minimums
  • Collect a reason for every criterion that fails
  • Return "stay bespoke" with the joined reasons, or approval when all pass
  • Demonstrate a block on thin evidence (1 user / 1 week / a few requests)
  • Demonstrate approval on strong evidence (several users / weeks / dozens of requests)

💡 Hint: Generalisation is earned by evidence, not taste — the gate exists precisely to overrule the engineer who feels ready to abstract.

Show solution

The discipline is procedural: you don't earn the right to generalize on taste, you earn it on evidence. This turns 'ship narrow' into a checkable rule.

def may_generalize(feature, min_users=3, min_weeks=2, min_requests=25):
    reasons = []
    if feature["distinct_users"] < min_users:
        reasons.append(f"only {feature['distinct_users']} users (need {min_users})")
    if feature["weeks_in_prod"] < min_weeks:
        reasons.append(f"only {feature['weeks_in_prod']}w in prod (need {min_weeks})")
    if feature["real_requests"] < min_requests:
        reasons.append(f"only {feature['real_requests']} real uses (need {min_requests})")
    if reasons:
        return False, "stay bespoke: " + "; ".join(reasons)
    return True, "evidence of real use - approved to generalize"

print(may_generalize({"distinct_users": 1, "weeks_in_prod": 1, "real_requests": 3}))
# (False, 'stay bespoke: only 1 users (need 3); only 1w in prod (need 2); only 3 real uses (need 25)')
print(may_generalize({"distinct_users": 5, "weeks_in_prod": 4, "real_requests": 60}))
# (True, 'evidence of real use - approved to generalize')
Exercise 6 · Your lead asks you to scale the FDE method across 4 teamsIndustry scenario

Context: Your tech lead wants the FDE loop to be every team's default, not one engineer's habit — and the quality of the practice must be visible across teams.

Your task: Design how you'd operationalise the FDE method across four teams, and write a scorecard that flags teams drifting back to big-bang builds. (Design + code.)

Requirements:

  • Require an outcome-first brief on every project
  • Default to thin slices (short time-to-first-use, few features in slice one)
  • Bake instrumentation/evals in from the start; productise only after bespoke is proven
  • Score each team on named-outcome, fast-first-use, thin-slice, has-evals, and bespoke-before-platform
  • Return a score, a grade (following vs drifting), and the list of failed checks
  • Show one team passing and one drifting on every check

💡 Hint: The scorecard is the same discipline turned outward: it makes "are we still doing FDE?" a per-team number instead of a vibe.

Show solution

Design (section 6, tech-lead rung). Make the loop the default and measure adherence:

  1. Outcome-first framing required in every project brief (a named customer outcome, not a feature list).
  2. Thin-slice-then-iterate as the default: first user-facing use within ~2 weeks, ≤2 features in slice #1.
  3. Instrumentation baked in so 'better' is measured every iteration (ties to Ch 5 evals).
  4. Path to productize only after bespoke value is proven (the generalization gate above).

A scorecard turns the practice into something a lead can see across teams:

def fde_scorecard(team):
    checks = {
        "outcome_first":     bool(team.get("named_outcome")),
        "fast_first_use":    team["weeks_to_first_use"] <= 2,
        "thin_slice":        team["features_in_slice1"] <= 2,
        "instrumented":      team["has_evals"],
        "bespoke_before_platform": not team["built_platform_first"],
    }
    score = sum(checks.values())
    drifting = [k for k, ok in checks.items() if not ok]
    grade = "following FDE" if score >= 4 else "drifting to big-bang"
    return score, grade, drifting

teams = {
    "payments": {"named_outcome": "cut refunds MTTR", "weeks_to_first_use": 2,
                 "features_in_slice1": 1, "has_evals": True, "built_platform_first": False},
    "platform": {"named_outcome": "", "weeks_to_first_use": 10,
                 "features_in_slice1": 7, "has_evals": False, "built_platform_first": True},
}
for name, t in teams.items():
    score, grade, drift = fde_scorecard(t)
    print(f"{name}: {score}/5 {grade} | drift={drift}")
# payments: 5/5 following FDE | drift=[]
# platform: 0/5 drifting to big-bang | drift=[all five]

✓ Checkpoint — you can move on when you can…

  • Explain the FDE method and outcome-first framing.
  • Design a thin end-to-end slice.
  • Iterate in a measured feedback loop.
  • Resist over-building; scale the method to a team.

Knowledge check check yourself

✓ Knowledge check

The FDE method says to ship the thinnest end-to-end slice rather than a polished component in isolation. Why does a rough pipeline the user can actually run beat a perfect module they can't?

Show answer
Because the whole point is learning fast, not shipping big. A slice that works end-to-end for one real case produces the feedback that tells you what to build next; a perfect isolated component produces none. In the slice_score model, not being end-to-end is the biggest risk penalty precisely because it leaves you flying blind.
✓ Knowledge check

What does the chapter identify as the most common FDE failure, and what discipline counters it?

Show answer
Over-building — reaching for the general, elegant system before proving the specific, ugly one solves the problem. The counter is to ship narrow and earn the right to generalize only with evidence of real use (bespoke first, product second).
© 2026 studybydoing.in · AI Engineering: Zero to Production · All rights reserved. · About · Privacy Policy · Terms · Contact
Educational content, provided as-is and without warranty. Code samples are examples — review, test, and adapt them before using in production. See the Terms of Use & Disclaimer. Use at your own risk.
© studybydoing.in