Big Sofa Tech Blog: To Rebuild Or Not To Rebuild?

At some point, most Engineering Managers will find themselves in front of their bosses trying to explain to them why they need to invest time and money into refactoring and cleaning up Tech Debt. This is not an easy thing to do. We have a product, it’s working, why waste time fixing old things when we can have new things? Well I found myself in exactly this position, except that I happen to work for a company that puts technology first. Big Sofa is a company that understands what it means to be agile, but also understands what the cost of being too agile can be, and what it does to your product.

There are three types of Tech Debt. Let’s go though the differences between them, before looking at how we decided to fix them:

1) Deliberate Tech Debt: Many software developers are opinionated and perfectionists by nature, but they also work for companies that want software and want it fast. They don’t have the luxury of spending months on every feature they work on. As a result, they sometimes have to compromise. They may have to cut a few corners here and there, which they swear they’ll revisit at a later date. Even with the best will in the world however, they rarely do – after all, there’s the next big feature to build!

2) Accidental Tech Debt: This can happen in one of two ways: either through unforeseen circumstances, or through poor working practices. Either way, the result is the same: a flawed design. Sometimes it can be rescued, but sometimes you just have to face the music and go back to the drawing board.

3) Bit Rot Debt: This is perhaps the most unavoidable and inevitable type of debt. As a system grows, so does its complexity. Unless you're a Matrix-style oracle, there is no way of knowing what the next few years will bring for your software. This means you may well be building components into your product that you had not initially planned for. Developers will come and go, each bringing with them a different way of doing things and their knowledge may not be passed on from one developer to another, so there may be a duplication of effort. Time can be unkind to software: technologies change, designs change, developers change and requirements change. 

Unfortunately, we realised  we were starting to accrue an unpleasant combination of all three types of debt, so it was time to do something about it! 

First decision, do we rebuild or refactor? Starting from a clean slate sounds appealing - no legacy, everything brand new and shiny – it’s every developer's dream. The downside is that it would be months, maybe even years, before we’d have anything to show for all of this effort. The business is understanding, but not that understanding. So why not do both? 

While coming up with a plan of action, we came across the Strangler Pattern. It’s a design pattern, which allows teams to rebuild aspects of a system incrementally, while remaining operational. 

The idea is to use a facade, which sits in front of your application. The facade never changes, but behind the scenes, your application is being rebuilt bit by bit while consumers are none the wiser. Our aim was to break down our singular, multi-functional monolithic application into smaller, separate microservices which all communicate with one another, so this was perfect for us! We’re in the business of video analytics and we have an application performing a vast array of operations: transcoding, frame splitting, transcription, extracting metadata, cropping, rescaling, machine learning... the list goes on! Our front end was also embedded into this monolith and we wanted to rebuild that using modern javascript frameworks in a Single Page Application. There’s also our API (which needed rebuilding from the ground up) not to mention a huge change in our system architecture to support this new microservice design. This means that DevOps would play a huge part in this rebuild. This was starting to become a daunting prospect, but definitely an exciting one!

Code wasn’t the only thing that had to change. We needed new processes to make sure we worked productively as a team; processes which meant we could ship code faster, make sure every requirement was crystal clear, keep the business up to date with progress and ensure every feature we built was up to the highest standard. 

So there we had it – a plan. Now all we had to do was execute it….


In the rest of this blog series, we’ll go into more detail about how we used this approach to rebuild our front end and API, split out our monolith into a host of connected microservices and restructure our system architecture. We’ll also be looking at  our working methodologies and processes, so stay tuned for the next post in our Tech Blog series!