One of the toughest decisions your software development team may face as you scale is deciding between keeping your current codebase and rebuilding on a new software architecture. In this article we will see what is so called sacrificial architecture and why sometimes it is better to build something from scratch instead of trying to continue and improve what already exists.
Rethink, restructure, and rebuild
Sometimes it takes less effort in terms of time and money to build a solution from scratch. Key kere is to rethink, restructure and rebuild. Of course it may bring a bit of frustration that the previous work “goes to the rubbish bin”, but in reality this know-know that you got, these lessons that you learned lead you to develop a much more powerful and scalable product, using the latest and fastest technologies.
Wait, but what is sacrificial architecture?
Many companies work on sacrificial architecture strategically. Often, companies build sacrificial architecture when creating a minimum viable product to test a market, anticipating building a more robust architecture if the market approves. Building a sacrificial architecture implies that software architects aren’t going to try to evolve it but rather replace it later on.
So, sacrificial architecture means accepting now that in a few years time the team will need to throw away what they are currently building. In other words, sacrificial architecture is a short-term solution to the current neads, which in most of the cases is used to go to market faster and test MVP.
Martin Fowler mentioned one curious thing about sacrificial architecture, he says that it is also about thinking now about the things that can make it easier to replace when the time comes but software architects rarely think about how to build an architecture to support its replacement.
Sacrificial Architecture: Case Studies
For very famous tech companies, deciding to rebuild their software systems from scratch was a brave decision and massive success. For others, it ruined them. It is all about trade offs, it is all about seeing the big picture and accurately calculating all the options, finding optimal solutions to your specific situation. So, let’s see some case studies where replacement lead to an exponential growth
eBay sacrificial architecture
eBay, one of the most successful companies in the world started as a set of perl scripts built over a weekend 20 years ago. After 2 years of operation, it was all torn down and replaced with a system written in C++ on top of the windows tools of the time. And 5 years later the application was rewritten again in Java.
The first question that pops up is were these early versions an error because they were replaced? What would you say? In most of the cases, leading software architects believe that it was the right decision at that time. Now, Ebay is one of the great successes, but much of that success was built on the discarded software of the 90’s. The right architecture to support 1996-ebay is not the right architecture for 2006-ebay. The 1996 one can’t properly handle 2006’s load but the 2006 version is too complex to build, maintain, and evolve for the needs of 1996.
When eBay started, it was like any other startup: they needed to find the feature set that would get people to use the service. Serving a large, concurrent user base wasn’t the challenge, finding product market fit was. And this happens to most of the startups nowadays. You can’t predict all the possible growth challenges and obstacles, the first thing is to prove that your idea is on demand.
Let’s analyze the situation again. At the beginning, eBay needed to iterate fast, so Perl made sense. Then, over the years, traffic was rapidly increasing, while the feature set became more mature. In this new phase of the company’s growth, they needed a more stable and scalable system. Moving from Perl to Java seemed like a wise decision because Perl was not a strict language syntactically and semantically, which made it suitable for fast development but not ideal for larger-scale programming. Java on the other hand, is designed to let developers write once and run anywhere. During the early days, they had only a few users, so there was no need for a complex architecture to ensure high traffic availability. When they found the features that drew in users, performance and high availability became essential to the business to grow.
Twitter sacrificial architecture
In 2020, Twitter launched its new public API. The release didn’t just contain new features. It was a rethinking of the overall architecture.
“Today’s launch marks the most significant rebuild of our public API since 2012. It’s built to deliver new features, faster, and to better serve the diverse set of developers who build on Twitter. It’s also built to incorporate many of our experiences and lessons learned over the past fourteen years of operating public APIs.”
Twitter public API v1.1 was implemented as a set of HTTP microservices, moving them away from a monolith. Even though microservices enabled Twitter’s team to speed up the development process, it resulted in scattered and heterogeneous endpoints as independent teams designed and built for their own specific use cases. Twitter needed a new architecture as the old one was not up to future expectations. The new version of Twitter API v2 needed to be more scalable to serve a large number of planned new endpoints that support new functionalities. It also had to provide more consistency for external developers and reinforce more uniformity.
In these examples, eBay and Twitter went through complete rebuilds of their architecture in order to have stable and performant systems that could scale and support new features. Their old architectures weren’t a waste of time; they were foundations that had to be sacrificed to get them where they are today. Interesting point here is that software architects don’t always throw away code because it’s terrible, but because needs have changed.
Google sacrificial architecture
At Google, the explicit rule is to design a system for ten times its current needs, with the implication that if the needs exceed an order of magnitude then it’s often better to throw away and replace from scratch. It’s common for subsystems to be redesigned and thrown away every few years.
In Apiumhub we see a lot of projects that have a common pattern when coming into a maturing code base denigrating its lack of performance or scalability. But here it is important to understand that in the early period of a software system teams are less sure of what it really needs to do, so sometimes it’s important to put more focus on flexibility for changing features rather than performance or availability.
“Modularity is the most important characteristic of a maintainable app. Modularity is the degree to which a system’s components may be separated and recombined. A modular app is not wasteful—parts can be changed, replaced, or thrown away without affecting the rest of the app” Justin Meyer.
It’s easier to write code than to read it. That’s why Martin Fowler suggests that the team who developed a software is ultimately the one to decide if and when to sacrifice it.
Also, it is important to highlight that new code isn’t always better. The old code has been used and tested by real users, using accurate data, and under real-world pressure. A lot of bugs have been found and fixed, and many iterations and improvements have been applied. If a decision of throwing a code away is due to a “if-condition,” probably all you need to do is a couple of refactoring iterations. When the code is in line with the current and future business goals, then you don’t need to sacrifice it.
Sacrificial architecture is a mindset that allows you to accept the idea of giving up your own code. Choosing the right time is entirely on you.
In conclusion, sacrificial architecture can be a great way to learn, however, it should not be an excuse for building low-quality software as it will be sacrificed anyway. Don’t be afraid to give up some of your own code but do it wisel, analyzing all the tradeoffs that you have.