
In Practice: Why We Push Back
In Practice is a recurring column about what actually happens inside software engagements. Not frameworks, not advice. What we find, what goes wrong, and what it means.
There's a conversation I've had with almost every client at some point. It usually happens somewhere around the third or fourth feature request — after the initial scope is built, when the product is running and the wishlist starts.
A founder or a technical lead comes in with something they want built. It's specific. It's thought through. Sometimes it's technically impressive. And it has almost nothing to do with what their users are actually asking for.
I used to just build it.
The assumption I was making
For a long time I operated on a simple model: the client brings the vision, I bring the execution. My job was to take what they described and make it real. If they wanted an admin console, I built the admin console. If they wanted an audit logging system, I built the audit logging system. If they wanted a communication platform, I built that too.
I built all of those things for one client. They went unused for months.
Not because the work was poor. The systems worked exactly as specified. But nobody — internally or externally — had asked for any of them. There was no user demand driving the wishlist. There was a vision of what the product should eventually look like, and the assumption that building toward that vision was the same as building toward traction.
It isn't.
The parts of the system that were critical — authentication, organization structure, the core user workflow — had evolved around all of those unused systems. When interest eventually came back, we'd essentially have to start from scratch. The code existed. The context it was built in didn't anymore.
That's a specific kind of waste that's easy to miss in the moment. Each individual build decision made sense. The cumulative effect was a product that had grown sideways.
The moment the model broke
The authentication system was homebrewed. It worked, technically. Users could log in. But adoption was slow and the client's team was spending significant time manually onboarding each new user — C-level executives walking customers through account setup one by one. The opposite of scalable, and nobody had connected the dots between the onboarding bottleneck and the authentication design.
I migrated it to a dedicated authentication provider. Kept the existing workflow, cleaned up the implementation, called it done.
Adoption didn't improve.
Eventually I did something I should have done much earlier: I asked a customer to share their screen and walk me through the process. Not to fix anything in advance. Just to watch.
What I saw was a system that made complete sense if you already understood it. Users had to create two accounts, verify the first, then manually connect the two — piecing together two separate emails with two separate confirmation codes to figure out which verified the account and which linked it. Unless you already knew the intended sequence, the process had no obvious path forward. The internal team had never flagged it because they were the ones doing the onboarding. They knew exactly what each step meant. They had never tried to complete it cold.
I collapsed the verification and connection into a single step and rewrote the confirmation email to include everything a user needed in one place. Users could complete the process themselves. Whether the broader onboarding workflow changes around that is a story for another day — but the technical barrier was gone.
That's the gap that a ten-minute screenshare closed. Not a sprint. Not a feature request. Ten minutes of watching an actual user try to do the actual thing.
What I understood in theory and now know from experience
I'd read the Lean Startup. I understood the build-measure-learn loop. I knew the right answer was user feedback first, code second.
But there's a difference between knowing something and having felt the cost of ignoring it. I hadn't felt it until I watched an entire product category go unmaintained because nobody had asked for it. Until I watched executives manually do work that a single UX change could have eliminated. Until I rebuilt authentication twice and got the answer not from the code but from a customer's screen.
The most honest thing I can say about that client is that when I raised the question of user feedback, I was told to treat the technical lead as the customer — someone with years of experience in similar industries on similar enterprise projects. The instinct was understandable. I'd made the same mistake myself — assuming that because I understood the problem deeply, I understood what the solution should look like. The issue wasn't the experience. It was that enterprise experience at scale, with established customer bases and existing infrastructure, is a different problem than an early-stage startup with a fraction of the resources and no installed base. The customers who would make or break this product had never been in the room.
I don't say that to assign blame. I say it because I made the same error — defaulting to fulfilling the wishlist instead of asking whether the wishlist was connected to anything a user had actually said. We were both working from the same wrong assumption: that the people closest to the product were the right ones to define what it should do next.
How I work now
I treat myself and the founder as two data points. That's it. We don't outweigh a single actual user expressing real friction in the thing they're trying to do.
If a founder asks me to quote a feature, I'll quote it. I'll plan it out, tell them exactly what it entails, and build it if that's what they want. What I'll also do — before any of that — is ask what the user evidence is. Not the theory. Not the competitive analysis. The actual signal: did a user ask for this, show frustration without it, work around it in a way that showed up in their behavior?
Features that competitors have aren't validation. They're observations. A competitor built that feature for their customers, in their context, with their data. Copying it doesn't move your users — your users have their own problems, and the only way to know what those are is to ask them.
The same standard applies to internal requests. Someone on the team flagging a painful process is genuine signal and worth taking seriously — internal improvements hone the engine and make it more efficient. But at early stage, if the engine of growth isn't working yet, there's limited value in optimizing machinery around a process that isn't running at scale. A single person's friction is a data point, not a mandate. The external customer experience is almost always the higher-leverage problem first. Knowing that, and saying so when the priority order gets inverted, is a significant part of the job.
Everything else is a hypothesis. The tools to test one before you build — design prototypes, user surveys, screenshares — cost almost nothing now. There's no reason to gamble a sprint on a gut feeling when you can find out what it's worth in a week.
You're not buying your own app. Your instinct about what should go in it is one input. The sooner that becomes the operating assumption, the more each build decision compounds toward something real.
If you're building something and want a second data point — one that comes without a stake in being right — that's the conversation. Start at def0x.com/discovery.