Feature flags: best practices, and seven anti-patterns to avoid
What is a feature flag? Four types of toggles, what to try before adding one, and seven anti-patterns that end up running code nobody has tested.
MVP stands for minimum viable product. The term comes up as soon as anyone talks about launching software, and most of the time it means a first version. The application, with fewer features.
Allen Holub points out that there are two definitions. The older one, Frank Robinson’s, does make it a product. That is the one most people have in mind. The other comes from Eric Ries, in The Lean Startup, and Holub sums it up as “the minimum thing that tests the viability of a product idea”.
It is not a version 1. It is not a product at all. It is a test.
An MVP answers a single question: is this product worth building? If the test passes, the idea is viable, and building it becomes a reasonable thing to do. If it fails, you avoid spending months building something nobody wants.
The ideal MVP, according to Holub, involves no development at all. His example: DoorDash’s MVP was delivering pizzas. That tested whether home meal delivery was viable, without a single line of code.
When it does take code, it stays tiny. Holub talks about an MVP that comes together “in a day or two, maybe a couple of weeks on the outside”. To get there, he borrows Ries’s method: take the smallest set of features you can imagine, cut it in half, then in half again, then once more. And test only one thing at a time.
In a more recent post, he tightens the limit further. A software MVP that takes more than a few days to build and ship is, in his view, far too big.
Because you cannot know in advance which ideas will work. When Microsoft measures the effect of its ideas through controlled experiments, only one in three improves the target metric. One third has no effect, one third makes it worse (Kohavi and Thomke, Harvard Business Review, 2017). Nobody knows in advance which ones. You find out through use.
Without a test, you find out after the building is done.
One app founder told his story in a video. In late 2024 he launched an online software product, which he built in public over three to four months. He hired a developer, for €25,000, and a graphic designer. At launch, plenty of people signed up. But features they considered essential were missing. His cash ran out, what the app brought in did not cover its costs, and he put it on hold.
This story says nothing about the quality of the work. It says something else. The budget was committed to a feature list before a single user had given any feedback. He found out what users needed at launch. By then, there was no money left to build it.
All three look alike: small, quick, often incomplete. They do not address the same uncertainty.
The MVP answers the question: does this product deserve to exist? What you keep from it is the answer.
The prototype answers a different one: does this design work the way we think it does? A whiteboard sketch of a screen is one. A model that tests how part of the program behaves under load is another. That one has to be written in production-quality code, since it then becomes part of the main codebase. Holub sums up the difference in two sentences: “A prototype tests a design. An MVP determines if a product is worth building.”
The proof of concept comes even earlier. It checks that a technical decision still under consideration will hold up. If you doubt the database can handle the load, you write a program that does nothing but write data to it and read it back. The result looks nothing like the final software.
The spike, lastly, comes from the vocabulary of Jez Humble and Dave Farley. In Continuous Delivery (p. 425), it is a throwaway implementation of a particular requirement, done to reduce an analysis, development or testing risk. The code gets thrown away. Only the answer counts.
Choosing the right tool starts with naming what you are unsure about. Uncertainty about value calls for an MVP. Uncertainty about the design calls for a prototype. Uncertainty about technical feasibility calls for a proof of concept or a spike.
Holub describes two schools.
The first wants to get the MVP into the hands of potential customers as fast as possible. The code can be sloppy. It is throwaway, and that is the word that matters. This school bets that the idea will fail, so it spends the minimum.
The second treats the MVP as the core of a “walking skeleton”: the first piece of a system that will then grow in small steps. It bets that the idea will work. So the code has to be production quality from the start. The scope stays tiny, and in Holub’s experience, quality code comes together faster than sloppy code.
Each one is defensible. Mixing them is not. “These two approaches cannot coexist,” Holub writes. Making a low-quality MVP the core of a system means building on a rotten core you can never get rid of.
In his September 2026 post, he leans towards the second school. Building the MVP in production code, with its tests and a decent interface, adds only about a day, in his view. And the result then serves as a walking skeleton.
Dave Farley prefers a design that evolves in small steps to big upfront design (video “How To Avoid Big Upfront Design”, Modern Software Engineering channel). As we see it, an MVP built in production code follows that path: it grows step by step instead of being designed entirely up front.
What the first school coded by hand, AI tools now produce. You describe the application you want, without reading the code the AI writes: that is vibe coding. Holub grants it a place: throwaway prototypes.
The app founder ended up there too. In 2025 he discovered vibe coding, and reckoned it would have taken him two days, for €0. On one point, his reckoning matches Holub’s: a test lasting a few days can show what the product is missing for its users before the budget is spent.
But throwaway code stays throwaway. The vibe-coded prototype answers the question about the idea. It does not become the foundation of the software that follows. What “it works” does not guarantee is covered in our article on building an app with AI.
An MVP that passes does not settle anything. Holub describes what comes next. You ship the smallest possible thing. The reaction is almost always: that’s nice, but… That “but” points to the next smallest change. You make it, ship it, and start again. He adds: no big upfront specification, even when the one receiving it is an AI.
This loop does not stop at launch. In our adaptive approach, every feature is a hypothesis tested against the reality of your users.
We develop your custom application on a fixed budget, invoiced at the end of each month for the work done. It is usable within a month. Usable does not mean finished: your teams use it from the first month, and that use decides what we develop the following month.
Why not plan everything from the start, the feature list and the schedule? That is the question asked in our article on the predictive and the adaptive approach.
Our guide covers Kohavi’s experiments in detail, and what the features nobody uses go on to cost.
Do you have an idea to test, or software you want built? Shall we talk?
What is a feature flag? Four types of toggles, what to try before adding one, and seven anti-patterns that end up running code nobody has tested.
How much should you budget to build an app? The figure alone is not enough: aim for a goal rather than a feature list, with users from the first month.
Predictive or adaptive approach? The real dividing line is not between waterfall and agile. It runs between predicting and adapting. What that means for software.