Borrowed Assumptions
A Good Product
Everyone knows what a good product is. It is simply a product that is good. Isn’t that obvious?
I admit I had not put much thought into this before becoming a software engineer. You use something and move on with your life. That is enough as a user, but not when you are the person building it.
Once you move into industry, “good” becomes quantifiable: engagement, conversion, retention, and so on. You run an A/B test; X wins against Y, and you ship it thinking that you improved the product.
Online experiments are one of the best tools we have for not lying to ourselves, but statistical evidence is not enough.
An experiment can tell you users clicked more, booked more, or came back more often. It cannot, by itself, tell you that you understood the user’s needs. You can improve a lot of your visible metrics in the short term while making the product worse and more frustrating for the users.
Often, people do not really want your product. They want progress in some situation, and it is your job to understand the situation.
Intentionality
I think a good product is mostly about intentionality: the intentionality to encode deliberate assumptions about the user, the problem, and the trade-offs.
A book is an easy comparison. When you read a good book, every line and passage feels intentional. It’s there for a reason: to advance a plot, develop a character, or make you feel a certain way. The pacing, prose, and content reflect the intentions of the author.
Will you read 50 pages of LLM-generated text? Unless you are getting paid for it, probably not. During the reading, you’re mostly trying to figure out the minimal set of information that was expanded into this gigantic body of text. You, as the consumer, are not interested in the artifacts of the expansion process.
The Information Problem
LLMs can generate all sorts of things now; there is no question about their usefulness. Like many programmers, I have spent much of the past year talking to AI, materializing ideas, realizing many were not worth pursuing, finding new ideas, and creating more small products.
Most of them were not great products. Like half got stripped and absorbed into other projects; a few became part of the daily toolkit; maybe one or two got close enough to good that I had other people try them. I’m not trying to downplay the impact of AI on these projects; most probably would not exist given how little time after work I get for such things.
The way we work with LLMs has an information imbalance. The prompt given to the model has far less information than the result will contain. There are many small decisions throughout this process. You specify only a few of them, and the model makes the rest. Those decisions do not remain open for later review. They are decided, built upon, and shipped as core parts of the product.
This can be great because it allows software to reach places it could not before. It can be harmful by offloading all the decisions to models outside your control that, even if well aligned, do not have all the constraints to make the correct decisions. For the most part, the model is trying to satisfy your needs in a single session. It has no concept of an overarching product and its trajectory and will reward-hack your product into oblivion given half the chance.
Eventually, you will hit a wall in progress because you no longer understand why the product is the way it is.
I’ll Just Write a Detailed Spec Then
This is everyone’s default solution. I will write a detailed spec. I will turn on dictation and talk for two hours. I will create a product requirements document. I will add examples. I will tell the model exactly what I want. This is just a skill issue. I will steer the AI better.
This helps, but only up to a point. If you remove all expansion, your spec starts becoming as large and detailed as the product itself. At that point, is writing the product in Markdown really that much better than writing it in code?
The harder problem is you do not know all your assumptions. Nobody does. If they were obvious enough to list, they would not be assumptions.
Web developers are spoiled here. There is a huge amount of web code, product writing, UI conventions, and SaaS sludge in the training data. The model often shares enough of your assumptions to seem smart. It knows buttons usually have hover states, that settings pages need toggles, or that dashboards need cards.
Move into a space with less common training data, and you see the problem faster. Ask it to make a game, design menus, handle progression, pacing, difficulty, input feel, visual feedback, and the tiny moments that make games feel good. Suddenly, the defaults are much less useful. You find out how many assumptions you relied on without noticing.
So What?
Before AI, implementation and intention were more tightly coupled. Not perfectly. Bad products existed before ChatGPT, obviously. But when you built a working prototype by hand, many of your assumptions were forced through the act of building. You had to be there, decide, and encode the decisions.
Now it takes a lot of effort to stay focused while the AI is doing the work and to know what assumptions are getting into your product. In a lot of ways, this is worse than tech debt. With technical debt, the product may still produce the intended outcomes and meet user needs. With assumption debt, you only have a plausible-looking product with unintended outcomes.
LLMs will get better. Better defaults, better design sense, more silly skill files to depend on. The list is endless. But this process cannot be automated if you are producing anything of significance.
Conclusion
It is cheaper than ever to create a product. I do not think it is cheaper to create a good one.
AI saves time on implementation; you can get to a prototype faster, get in front of users faster, and face reality faster. That is very valuable and also rather dangerous because the demo is usable before the hard constraints of the product are visible.
The problem is that a prototype can now masquerade as a product because reaching this stage no longer requires the same product work.