How to Rewrite a Web Application

You're about to start rewriting a web application. If your first step is to choose your technology stack and start estimating features: STOP, you're doing it wrong.

A screen-for-screen, feature-for-feature rewrite is a massive waste of opportunity and a huge waste of time and money.

Let's talk about how to do it properly.

The Big Lie

The big lie of software rewrites is: "the requirements are already there in the existing software". If you think that, you're lying to yourself.

That's like saying "the previous process that resulted in this software was perfect". No, it wasn't. I've seen so many teams get themselves in trouble by starting with this mindset.

Assume the existing software is full of requirements holes and unneeded fluff.

The old app is an unkept garden. There are flowers there, for sure, but you need to pull the weeds.

The Port Problem

When your plan is to do a "tech lift" or "port" of the existing software (that is, a screen-for-screen, feature-for-feature rewrite) you aren't just porting the features.

You're also porting, at the very least:

What's The Better Approach?

A proper rewrite of an existing application is not first a technical project. It starts its life as a research project.

But it's an incredibly low-cost research project, because all the years of testing have already been done. The existing software and its users are a gold mine.

A research-based rewrite saves time, money, and frustration. All you have to do is take advantage of all that existing test data.

The Cow Paths

In terms of software, the "cow path" is the workflow that users adopt to accomplish their work, when that workflow isn't explicitly implemented in the software.

I once worked a software rewrite where there was an invoicing feature that had a throwaway "notes" field to add open text notes to an invoice. Users used that field for all sorts of things. In the end the years of data in those notes fields were a massively useful (and, for the stakeholder, terrifying) research result that drove new requirements.

Whether through user interviews, user observation, data analysis, or analytics the existing software may contain a treasure trove of workarounds. Once you know how the users need to work, you can make that path the easy path in the new software. You may also realize what you need to prevent users from doing.

The great thing is, none of this is guesswork. The answers are right in front of you in the old software.

Research how the old software is used. Then, in the new software, pave the cow paths.

The Why Down

I've written before about the process I use to create the best outcomes for software development. I call it "the why down".

At its core, it's about finding the problems that need to be solved and determining the least amount of software needed to solve those problems.

As it turns out, the same mindset works fantastically to produce a successful software rewrite. Take any feature in the old software (and all the implementation details under-the-hood), and:

  1. Ask "why" until you arrive at the original problem the feature is solving.
  2. Determine if the old problem still exists.
  3. Determine if the old feature is still the best way to solve the problem.
  4. Determine if this or other features also solve any other original problems, and consolidate what features are really needed.

In other words, the new software needs to solve the set of problems the old software solves. That doesn't mean it needs all the same features.

The Design

There is an extremely valuable piece of design data you can extract from the old software and its users: how often do people follow a particular workflow?

The more often users use a particular set of features, the more they can be designed for "power users". You can make often-used features more dense, with more options grouped on one screen.

The less often users use a particular set of features, the more they can be designed for hand-holding. You can make infrequently-used features less dense, spread across more screens with less options. That way you can make each step of the workflow as clear as possible.

Why? Cognitive load. The less users use a feature the harder it is for them to remember how to use it. On the other hand, users who use features very often can develop cognitive muscle memory and don't have to rely on documentation.

Less-used features are tailored for ease-of-use, and more-used features are tailored for speed-of-use.

The same is true for the complexity and usability of all features. If something is hard to use in the old software, there are two possibilities: you don't need that feature after all, or it can made easier-to-use.

People will already struggle with new software, even if it supposedly matches the original. Give users something more thoughtful and usable than what they had before and you build a lot of goodwill which comes in handy when bugs crop up in new systems.

Your designers can (and should) take into account what can be gleaned from the old app to make the rewritten app even more usable than it otherwise might have been.

The Stack

Choosing a stack for a web application is a daunting task these days. JavaScript frameworks abound. Open-source utilities proliferate. But choosing a stack becomes a much less stressful "let's hope this goes well" experience when you've done the groundwork we've talked about so far.

You may realize that entire swaths of problems that need to be solved (that's a better way of thinking than "features") can be solved with 3rd-party tools and APIs that weren't available when the old software was designed.

I once worked a rewrite where we realized 80% of the code was to support problems that were solved by content management systems and a file sharing API. We integrated two existing 3rd-party tools, and rewrote the other 20% in a stack that we knew would work for the remaining custom design.

Having a clear picture of the needs of whatever features need to be created also helps choose the stack. You know what you need to accomplish, and you can pick your stack accordingly.

Avoiding technical debt and choosing the right stack also depends on your designers making smart choices for a web application. If they go crazy in Figma designing non-standard, non-native controls that all need to be custom built, you are hurting your team and your users. Prefer native controls whenever possible, and use well-tested, accessible UI libraries for everything else. Make custom-built controls earn their way into your apps, if at all.

Stack choice is not all-or-nothing. But to get out of the myopic view of feature re-creation, you need to think in terms of the "why" of a feature, and understand how users use the old app. If you do that, you open up your world of possible solutions, likely saving time, money, and frustration.

The Release(s)

If at all possible, avoid a single release where you completely replace the old web app. Instead, release new features as-you-go to a beta test group of users.

That can be a challenge under some circumstances. I worked a rewrite of software running a large company, where the new system needed an entirely new database.

We still released iteratively, and resolved the data with a combination of automated transfers of data between the old and new systems, as well as utilizing our most agreeable users to do double entry. Double entry also became a way to test for holes in business logic, bugs, and usability issues.

The best result from double entry was that users wanted to switch to the new web app as soon as possible because it was so much easier to use, and resulted in more reliable data.

Don't think of "replacing the app", think "here's the new way to solve the same problem".

Plan releases using the Minimum Solved Problems approach, where each release defines a set of problems that are solved.

When you iteratively release, it's much easier for the designers and devs to handle feedback and problems, and you can pivot when needed.

The Course

Everything we've talked about here can be practiced and learned. You just need to adjust your approach and your dev culture when it comes to rewrites.

If you're working on, or about to work on, a rewrite, and you think your team would benefit from training on how to do this, I include more on all of this in my Udemy course How to Build the Right Software (and Choose the Right Stack).

It dives into everything we've talked about in this blog post and more. Identify the underlying problems, find the best solutions (for you and your users), and choose the right stack to implement it. It includes quizzes, a free PDF worksheet, and I'm in the forums answering questions.

A Rewrite Can Be an Eye-Opening Joy

A rewrite can be a special kind of software project. You aren't blind to what is needed. The existing users and software are a research treasure.

Once you know why each feature exists, and what problems need to be solved, winnowing down the actual features needed is extremely satisfying.

Realizing you don't need as much software as you thought, finding just the right stack choices to ease implementation, and watching users want to use the new app can be a joy.

You just have to approach a rewrite properly.