The two modes of product engineering
One of the most important skill for a software engineer working on a product is to be able to switch between launch mode and stability mode.
This idea has crystalized in my head over the last few years of working on digital products in different environments. Engineers that are able to make precise calls on when and how to move between these two modes will be successful in whatever context they work in.
The idea is that product development, or rather feature development, moves in cycles. But not cycles of intensity, as I have heard many many times. But rather in cycles between launch mode and stability mode. The product teams that are able to align on this idea will be able to collectively navigate uncertainty, user feedback and long-term maintenance.
This idea is pretty abstract, I do not have a specific set of rules that will work for all teams out there. But I do think that the core idea is universally applicable. You have to decide when to make the switch between the modes, and what level of polish is expected in an MVP in your product.
The different modes should affect the daily priorities and trade-offs. It should guide internal discussions about scalability and maintainability. And it should always be a factor in helping you decide what to work. Or perhaps more importantly: what not to work on.
Launch mode
Launch mode is all about moving fast and getting something into the hands of your users. The goal of this phase is get the flywheel of learning and measuring in motion, not nailing every single detail. I try to think of it as getting a first usable iteration out as quickly as possible, and then figuring out a direction of improvements. Try to keep a short-term perspective here. Nothing is for certain yet, and any assumptions you make might as well be invalidated tomorrow. Trust the process of iteration, embrace uncertainty.
These are guidelines or soft principles I try to adhere to while in launch mode:
- Constantly ask: what can I get away with?. Copy-paste code, hard-code some number, actively look for shortcuts
- Complete the core flow. Do not spend time on improving the CI pipelines or the design system. Take note when things pop up along the way, but do not lose track of completing the core.
- Prioritize ruthlessly Make sure what you work on is critical for the core flows to make sense. It is better to add things back in once you complete the core, then to delay the release of the core to include details that might not be important.
Stability mode
Stability mode is about building a foundation for long-term success and growth. This is where you invest in the things you know are important for the long-term. Things like deep test coverage, introducing abstractions to make to improve reusability, and other optimizations. The key here is uncertainty is hopefully lower, so this work will payoff in the long run.
One area with a large ROI (return of investment) in most projects is finding ways to prevent and/or detect regressions in the system. Any improvmements you do to assure the quality and integrity of the system will pay off over time. Engineers can be more or less confident in making changes to a system, and anything that helps is worth a lot. This could be in shape of static code analysis, integration tests or increased observability. Anything that makes it less daunting to change the system while it is running.
Another important area to invest in while in stability mode is technical debt. This is where you rethink some of the previous choices you made. Make sure you set yourself up for success over time, and make the system easier to maintain. This is different for every product and team of course, but the basic idea is to continuously check on the various parts of your running engine. Are all the parts optimized and performing at their expected capacity?
These are values I try to stick to while in stability mode:
- Prioritize code quality, readability and reusability
- Invest in automated quality assurance. Make it harder to accidentaly break the system.
- Continue to iterate, but stop guessing. Listen to the users using the feature. Invest in product logging, and try to collect the hard facts.
- Focus on raising the bar, in every aspect you can think of. Polish the details, make it pretty
- For bugs that are eventually surfaced, invest in preventing it from ever happening again.
When do we switch?
One of the key metrics that can help you decide what mode to go for is uncertainty. What do you actually know about the user and how they will use this feature? If uncertainty is high, you should probably spend time in launch mode. This will help you get something measurable out, and start collecting data and understanding. On the other hand, if you already know what to build, and how it will be used, you might aswell make it great from the beginning. I really want to stress this, if you are certain that what you are building is right, let it take time and get it right from the beginning. You can still build iteratively, but do it for the right reasons. Avoid taking shortcuts for a cool demo, instead iterate with stability in mind right away.
I want all the teams I work in to adopt this mindset. If everyone involved in builing the product understands this core idea, and act accordingly every single day, you have a higher chance of success. You will be able to move fast and launch features as a proper team. I also find it a lot easier to produce great work as an engineer when we all trust this process.