Product market fit for engineer founders: why build instincts stall pre PMF, how to track learning speed over features, kill vanity metrics, and read retention.
The first startup I helped build from nothing had beautiful architecture. Clean layering, typed everything, a CI pipeline that ran in under three minutes, a data model I was quietly proud of. It also had almost no users who cared. We had optimized a system that nobody had asked for yet, and we had done it well, which is the most expensive kind of wrong.
That project taught me something I now believe most engineer-founders learn too late: the skills that make you good at building software are the exact skills that slow you down before product-market fit. Not because they're bad skills. Because they're aimed at the wrong problem. Before PMF you are not building a product. You are running a search. And the instincts that make a great system-builder make a mediocre searcher.
I've spent six years shipping production Flutter and Firebase apps and I now lead engineering at a startup out of Dubai. What follows isn't theory I read in a book — it's the mistake I keep watching strong engineers make, myself included, plus the operating model I use to stop it. If you think in types, invariants, and test coverage, this is about pointing that same rigor at the one problem that actually decides whether your company lives: finding product-market fit.
An engineer's job, most days, is to reduce uncertainty in a system you already understand. You know what "correct" looks like. The spec exists, or you can infer it. Your work is to close the gap between the current state and a known-good state as reliably and cheaply as possible. Idempotency, invariants, test coverage, "make illegal states unrepresentable" — all of it assumes the target is known and the challenge is hitting it consistently.
Pre-PMF, none of that holds. You don't know what correct is. There is no spec because the customer hasn't told you what they'll actually pay for, and half the time they don't know either. The target moves every week. In that world, the engineer's reflexes turn into traps:
The last one is the killer. Engineers are gradient-descenders. Give us a loss function and we'll walk it down beautifully. The problem is that before fit, the loss function you're handed is a lie. You need to find a better one, and finding it is the whole job.
Here's the reframe I keep coming back to: pre-PMF your codebase is not the product, it's lab equipment. Its job is to run experiments cheaply, not to be correct. The moment you start treating early code as a durable asset instead of a disposable instrument, you've quietly switched from searching to building — and you've done it before you've earned the right to.
Here's the trap that got me. A number that goes up feels like progress, and engineers have deep respect for numbers that go up. Compile times going down, throughput going up — that's the texture of real work. So when signups tick from 40 to 120 after a launch, the same reward circuit fires. It feels like the gradient is pointing somewhere.
Most of the time it isn't. The metrics that are easiest to move are the ones that correlate least with fit:
The tell is simple: a vanity metric measures your effort; a real metric measures their behavior. If the number moves because you did something (posted, launched, ran ads) rather than because users came back on their own, it's vanity. The metrics that actually track fit are the annoying ones — cohort retention, the shape of the curve after week four, how many people come back without being poked. They're harder to move and slower to read, which is exactly why they're honest.
A useful discipline: for every metric on your dashboard, ask "could this number go up while the business gets worse?" Cumulative signups can (churn hides underneath). Traffic can (you spent more on ads). Week-4 cohort retention can't — if it rises, something real improved. Keep the metrics that fail that test off your primary dashboard entirely, or you'll anchor on them by accident.
On a B2B tool my team shipped out of Dubai, weekly signups looked healthy for two months. Two of my engineers were already scoping a rework of the onboarding to "handle the growth." Then I split the chart by cohort and looked at week-4 retention per cohort. It was flat at roughly 8% and had been the entire time. The topline was rising only because we were spending more attention on top-of-funnel each week. We were pouring water into a bucket with a hole and congratulating ourselves on the size of the pour. I killed the onboarding rework that afternoon; there was no growth to handle.
The fix wasn't a fancier dashboard. It was one chart — retention split by signup cohort, plotted week over week — that we should have been looking at from day one. If you build exactly one analytics view before launch, build that one.
Once you accept that PMF is a search, the question changes from "how much did we build?" to "how fast are we learning?" The output that matters pre-fit isn't features. It's validated or invalidated hypotheses per week.
This is the reframe that changed how I run early-stage work. Think of it like a build pipeline, except the artifact is knowledge:
I track a literal count in the same standup doc where we track sprint work: how many distinct hypotheses did we resolve this week? Two is a good week. Zero means we spent the week building, which pre-fit is usually a bad sign, not a good one. It reframes the whole team, too — an engineer who shipped nothing but killed a bad hypothesis had a productive week, and saying that out loud changes what people optimize for.
The founder-engineer's real edge isn't shipping features faster than the next team. It's instrumenting the search so each loop teaches you more per unit of time. You are optimizing the meta-system — the rate of learning — not the product. If you want one mental model: you're not writing the program, you're writing the test harness for reality, and every experiment is an assertion about what the market will do. The team with the shorter learning loop wins, even if they write worse code, because they find the truth first.
Engineers trust what's countable and distrust what isn't. A dashboard feels like truth; a sales call feels like an anecdote. Pre-fit, that instinct is inverted from reality. Quantitative data tells you what happened. It almost never tells you why, and before fit, why is the entire game.
Ten well-run customer conversations will teach you more than a month of dashboard-staring, because they surface the thing no metric can: the words people use, the workaround they've hacked together, the moment their face changes. I've watched a prospect describe the ugly spreadsheet they maintain by hand at 11pm — and that spreadsheet told me more about the product than any funnel ever did.
A few things I had to unlearn about customer development:
Treat qualitative data like logs from production. You don't dismiss a stack trace because it's "just one occurrence." You read it, because it's a real event that reveals how the system actually behaves. Customer calls are the stack traces of your business — and just like real logs, the pattern that repeats across five of them is the one worth acting on.
Engineers already know how to do this; we just don't apply it to the business. When you hit an unknown in code — a new API, a tricky migration — you write a spike: throwaway code whose only job is to answer a question, explicitly not built to last. Nobody reviews a spike for architecture. Nobody writes tests for it. You learn the thing and you delete it.
Every pre-fit experiment should be a spike. The deliverable is an answer, not an asset.
// Not this: a proper, reusable, tested featureclass InventoryForecastService { final Repository repo; final CacheLayer cache; final RetryPolicy retry; // ... two weeks of careful work before a single user sees it}// This: whatever answers the question fastestFuture<void> fakeForecast() async { // I manually computed the "forecast" in a spreadsheet the night before. // The app just shows my hand-made numbers to 5 pilot users. // If they act on it, THEN I build the real engine. await showHardcodedForecast(pilotUserId);}That second block is embarrassing to a good engineer. Ship it anyway. The classic lean-startup experiment patterns are all "cheating" from a craftsmanship view and correct from a search view:
One rule keeps this honest: set the kill criterion before you run the test. "If fewer than 30% of pilot users open the forecast twice in the first week, we drop it." Pre-committing the threshold is the same discipline as writing the assertion before the implementation. It's the only thing that stops you from moving the goalposts once you're emotionally invested in the code you wrote. Write the number down where the team can see it, ideally in the same doc as the hypothesis, so future-you can't quietly negotiate it upward.
| The question you're answering | Cheapest test | What a "yes" looks like |
| --- | --- | --- |
| Does anyone have this problem? | 5 customer interviews | 3+ describe the same pain unprompted |
| Would they pay for a fix? | Landing page + payment intent | Cards entered, not just emails |
| Does the workflow actually land? | Wizard of Oz | Users complete the loop and come back |
| Is the automation worth building? | Concierge (manual delivery) | You're drowning doing it by hand |
| Do they want this specific feature? | Fake door button | Click-through above your pre-set bar |
The point of the table isn't the exact rows — it's the reflex. Before you open your editor, ask "what's the smallest thing that could kill this idea today?" and do that instead.
PMF isn't a notification. It's a change in the shape of your feedback, and if you're instrumenting the search you'll feel it before any single dashboard confirms it. The signals I've learned to trust:
The honest version: you usually feel fit before you can prove it, and you can fool yourself, so you still check the retention curve. But when several of these fire at once and the qualitative tone shifts from polite to demanding, that's the curve bending. That's when the search ends and the building begins.
A word on the number people want and I won't give them: there's no universal "good" retention percentage, because it depends entirely on your usage frequency. A tool people genuinely need once a quarter has a very different honest curve than a daily app. Don't chase someone else's benchmark. Chase the shape: decaying to zero means no fit; flattening on a plateau means fit, whatever the height of the plateau turns out to be for your category.
Here's the discipline that's hardest for people like us. The moment fit starts to show, the engineer brain wants to finally build it right — rip out the spreadsheet backend, add the queue, shard the database, wire up the observability stack we've been dreaming about. Resist it a little longer than feels comfortable.
Almost nothing you build pre-fit survives contact with real scale, because you were guessing about the workload. Real users route around your assumptions. The queue you'd have built for the imagined use case is the wrong queue for the actual one. Premature architecture pre-fit isn't just wasted work — it's load-bearing wasted work you now have to maintain and unwind, and it makes you slower to respond to what users actually do.
My rule of thumb for scaling a startup's tech stack:
The waste isn't building the wrong thing early — that's cheap and disposable if you kept it small. The waste is building the durable wrong thing early. A throwaway spike costs you a day. A "proper" platform for a product nobody wanted costs you the company. I've paid both bills; the second one is the one that hurts.