You have been working on building a wonderful piece of software, that people actually love using. It solves a problem, and people would be really upset if it went away tomorrow. You’ve finally achieved product market fit at this point.
Things are going great. There’s money hitting your bank. People never get tired of singing your praises, how your product is way better than every competitor, and they’re really enjoying it. Even people who don’t end up buying the product for reasons of their own, always mention the awesomeness of your execution.
All of this has stopped mattering to you now. Your eye is on the next target. You have a larger vision, a product that has more features, is faster, is more reliable, is more beautiful.
You’re right. A lot of things happened during building version 1 that you knew were trade-offs you just had to make to survive. There’s a lot of debt, and while everybody’s enjoying the current wave of love, you know one of these days this debt will come due.
There are sure signs of it. New features have become difficult to add, the code is full of leaky abstractions, how you planned the solution when you started building, and how it has turned out to be today is different.
I don’t know if you’ve been there. I have, quite a few times. With companies I worked at and with my own projects.
The first thing that comes to mind is, “This calls for a rewrite!”
9 out of 10 times this is said about a codebase it is a statement made in overconfidence and hindsight bias.
A lot of rewrites fail. I’ve seen about 4 full rewrites, been the person to make the stupid call at least 1 time, and I can tell you. Most rewrites fail.
It requires a lot of resources. A lot of time. A lot of thought to get one to work.
Why are rewrites difficult?
Software grows like an organism. When you build the first version out, there are a lot of bugs. Things break often, doesn’t matter how hard you’ve tried to make something without bugs. The real world doesn’t care. Your users don’t care.
You keep on fixing those bugs. Over time (a lot of time) the bugs for existing functionality start to decrease. You’ve by now handled a ton of edge cases. Some of them documented, some of them not so much.
When you begin work on a rewrite, you don’t understand all of the code. It was probably written by someone who was there before you. Even if you do have context, you probably don’t remember a lot of things.
This makes the recurrence of bugs inevitable. You will come across a lot of edge cases you had fixed in the old version but you failed to account for in the new one. Good software takes time (about 10 years). You can’t skip it.
There’s another issue. While you’re working on the re-write there is already a version out there being used by people. Your users depend on the current version, they can’t just wait it out till you’re ready with a new version.
It becomes a race between the current version and the new version. Your current version has a head start, your rewrite has to be done faster than the current version improves. If the work on your rewrite happens slower or equal to the speed the current version is improved, you will never be able to catch up. If it is a little faster, you will be able to catch up, but that will take time. Remember you still have a (technical) debt payment coming due.
Your rewrite has to be done significantly faster than the current version improves. This will mean you need to optimise your resources.
The only thing on your side is, you’re not exactly starting from scratch. You have way more domain knowledge you did when you wrote the first version, you already have a good team, and you have the technical foundations figured out (i.e. you don’t need to worry about deployment). That’s about it.
Here’s the conclusion I’ve come to on rewrites
9 out of 10 rewrites that have their release date more than 6 months in the future fail
The one successful rewrite that worked in my experience was the one where we had a hard deadline for 3 months, with an enterprise customer already waiting.
Yes, it’s biased. Yes its just from my experience. But you’re reading MY blog, not Wikipedia, so that’s what you’ll get.
How to make rewrites work?
Hard production deadlines are a last resort, and the crunch is a bad place to be in. Only take that road if you’re the good kind of crazy.
Here’s how I think of making rewrites work. Heard of The Ship of Theseus?
It’s a thought experiment that asks if a ship has had all of it components replaced with different ones, is it still the same ship?
If 98% of all atoms in your body are replaced every year, are you still in the same body as you were when you started school?
So, if over time you rewrite all modules in your codebase is it same codebase you started with?
And it’s not difficult. You have to spend a lot of time figuring out to run two versions together. If you’re building a frontend you have to figure out how to send a significant amount of extra JS to the client. If you’re replacing a microservice you have to be super careful to not break the API. But it’s possible.
Instead of going on this epic journey to rewrite the whole codebase, start smaller. What’s the most irritating part about your application? Figure that out, and rewrite that.
It’s not that big of an insight as I’ve made it to be, but it’s often not even thought about. It’s a mistake I’ve made.
The Undercover Rewrite
The Best Rewrite Story I’ve Ever Heard Of
Mike McDerment was running a design agency in early 2000s and after getting tired of making his invoices manually using Excel and other tools he had at his disposal, he decided to build something better. He created FreshBooks.
After a few years when FreshBooks had enough traction, he raised a funding round of $30 Million to scale to the next level. By this time, FreshBooks had a lot of “founder code”, and he too saw the debt coming due.
His solution. Rewrite everything.
He didn’t go the obvious way and ask people from FreshBooks to rewrite everything. He went ahead incorporated a new company separate from FreshBooks and got a team together – to build a competitor of FreshBooks. Gave them initial financing, and became their investor. Their next round of financing depended on them getting to an MVP, and then next pump of cash on another milestone.
Slowly, the new team at BillSpring (what the undercover company was called) started taking away customers from FreshBooks. It costed $7 Million, but the new product was working.
FreshBooks’ customers were cancelling saying they were moving to BillSpring. What looked like a threat to people at FreshBooks was a sign of things working to Mike.
It all went according to plan, one fine day BillSpring’s customers received an email that the company was now called “FreshBooks”, and the old FreshBooks became FreshBooks Classic. The existing customers of classic were invited to try the “New FreshBooks”.
Some people are the right amount of crazy to make great things happen I guess.
UPDATE: Christopher who was part of the rebuild corrected that people at FreshBooks knew of the rewrite, it was a complete secret externally