Iterative software development allows us to evolve our product and gradually learn as we go. We take small steps toward the desired outcome. Yet the urge for big upfront solutioning remains dormant in our DNA. It is in human nature to believe that starting over would be easier. Or better. Or faster.
There are a hundred reasons why the big rewrite is a bad idea and a hundred blog posts explaining why. In 99% of cases, you can find a way to gradually evolve toward your desired outcome. But what if you can’t? What if you reach a point where you need to rewrite a significant part of your product? How do you handle that in a feedback-driven environment?
Let’s take a look at this scenario:
You’re running a SaaS product with a customer dashboard. It’s the first thing your users see when they log in, and it contains handy widgets that give them insights and an overview. Unfortunately, the dashboard looks like it was designed back when the Zune was up and coming. The designers have complained long enough: it’s time for a complete overhaul of the look and feel. This new dashboard is not just a cosmetic improvement. We have come up with new visualizations and widgets for our customers. We will remove old, unused stuff to fight dashboard clutter. The developers believe this is the right moment to ditch the ancient AngularJs for Vue3. A big step indeed.
This poses a problem. Incremental agile software development tells us to evolve the dashboard toward the new design. We don’t want to lock ourselves in a studio and come out with Dashboard 2.0 three months later. We’re merely guessing whether we’re building the right thing by postponing the feedback that long. That’s dangerous. But we also don’t want the jarring user experience of having some widgets in the new style and most in the old. Let’s not even mention mixing Angular with Vue.
Finally, changing a live, active product will create resistance. Given enough users, someone isn’t going to like the redesign. That one widget we dropped turned out to be loved by a single vocal user. Pleasing everyone is impossible.
A clean way of tackling this is building the new design in parallel. Our system will have two dashboard styles, which we can toggle per user. We start with a dashboard with only the single most valuable new widget. That’s something we can build in an iteration.
We could hide this behind a feature toggle, but that leads to delayed feedback. More likely than not, we will only flip that toggle once we consider the new dashboard “done”. We’ll go months without gathering actionable feedback. We risk building the wrong thing. Long-lived feature toggles are as bad as long-lived feature branches.
A cool workaround is to hide this new dashboard behind a “Preview” button. Our users still have their old trusty home page, but they can get a taste of what we’re building. They can toggle between the new and old dashboards with the click of a button. This gives us instant feedback on the new design, which we’ll use to inspect and adapt. We can evolve this new dashboard while listening to our users.
At a certain point, our new dashboard will be good enough to replace the old one. That’s when we change our “Preview” button to an “Upgrade” button. Customers that choose the upgrade get the fancy new dashboard and lose access to the old one. New customers only get the new one.
After a while, you’ll have only a handful of clients who refuse to upgrade. That’s a fantastic target for product managers to study. Interviewing these people will give valuable insights into how our product is used.
Gradually phasing out our old dashboard allows us to serve our customers while gathering feedback. We can course-correct the original redesign along the way to get the best product. By giving our users the agency to switch whenever they want, we avoid the typical resistance to change.
We can delete the toggle and old code when everyone is at the latest version. At that point, we’re a few months later, and our users have already validated their shiny new dashboard.