How to make software architecture trade-off decisions

How do you come up with the best software solution for a problem and pitch that choice to both your technical and non-technical peers in your organization? And what are some common pitfalls in comparing your options?

A simple framework that has worked well for me for all kinds of technical decisions is prioritizing a set of criteria and mapping the possible solutions to them in tiers. Here’s how it goes:

Mapping the way forward

Who’s right?

Say you have already identified a shortlist of potential solutions, and listed out some benefits and disadvantages to each approach as pro and con bullet points.

Solution A has the most pros attached to it, you circle it in bold, and you proclaim it was the winner in your review session. As you’re describing the options, it becomes more clear not everyone is as convinced.

Bert makes it clear he favors option B, and cites several additional cons for all the other solutions, including your favored option A. You add these to the list.

Christine wants to ship the feature yesterday. Which solution gets it out of the door quicker? You indicate Solution C.

Daniel likes the more long-term focused option D. He disagrees with the relevancy of some cons Bert mentioned for D, and a technical discussion erupts of which you’re not sure whether it’s relevant for the task at hand.

You reflect back on happier times, when a review session went more smooth and everyone in the room was okay with going with the option with the most positive bullet points. Although, you recall that led to some difficulties down the road and may not have been the best option in hindsight.

Who was right? It seems everyone was, to some extent. How could you have prepared your design better, and evaluate the importance of a particular characteristic to another? To answer that question, we need to take a step back and evaluate what’s most important for your situation.

Context matters (It Depends!)

What’s more important for your team or organization for this particular feature or project?

Is it the users experience in the app (e.g. reduce loading times)? Reduce risk for data loss in a migration? Total Cost? Maximize independence? Minimize maintenance effort for another team? Removal of deprecated flows? Not make the piling tech debt even worse?

A technical trade-off decision depends on context, and selecting these most important criteria for your solution allows you to capture and describe it. Technical capabilities depend on what’s built or needs to be built, team availability, market context, appetite for risk, budget and so on.

Capture what’s most important, and highlight the top criteria in bold. Describe how a High, Medium or Low scoring solution would look like. You can discuss these trade-off evaluations with various stakeholders beforehand so that everyone is on the same page and knows what we’ll end up comparing solutions against.

You can follow this approach for choosing vendors, cloud providers, migration strategies, front-end frameworks, service design guidelines, new feature architectures and so on.

By having alignment on what the most ideal solution would look like, it will make it easier to navigate through possible alternatives and highlight the trade-offs between solutions for non-technical peers. If the importance of a particular criteria would change, it will be straightforward to re-assess the alternatives.

Work out the technical details for each solution and call in expertise as needed. Make sure everyone is aligned on what we’re trading off and which one fits the project better, to avoid getting into the weeds on matters that may not affect your project.

There’s a couple more things to watch out for, however …

Common pitfalls

Choosing between ‘the hack’ and the ‘right way’

“There’s never enough time to do it right, but there’s always enough time to do it over.” — John T. Bergman

A common trade-off is development time. Should we opt for a quicker ‘hack’, and maybe ‘do it properly later’ — or ‘do it right from the first time’ ? The quicker hack allows us to release and get feedback faster, but may fall short in some areas such as performance, reliability or developer experience. If you find yourselves in the situation where the hack is always preferred and the technical debt your team has taken on shows pains in the systems uptime or developer experience, you should make sure to take this context of a blown ‘debt budget’ into account.

You can do this by describing the total cost of ‘the hack’, what lies in the ocean beneath the tip of the iceberg. Often we omit the costs it incurs for our team, or especially other systems or teams down the road. Don’t fall into the trap of always building shortcuts because everything always starts off as ‘just an experiment’. That approach works, if these experiments are consistently either changed or removed after they have concluded.

Secondly, when the hack is chosen and your team as a result chooses to take on the technical debt, make sure to document it. We employ a separate page on our wiki describing the debts, any relevant past architectural decisions and linking the tasks required to fix it properly. This makes it more clear why a piece of code is a certain way and why it’s best not to use it as an example or foundation, and help nudge future projects in the right direction.

When new features or iterations are planned, make it a habit to identify which of those tech debt pieces would make sense to tackle as part of the project. They may improve developer experience and make it easier to release iterations, resulting in fewer surprises in bugs, performance issues or increased development times.

Too few or too many alternatives

How do you come up with different solutions that would make good shortlist candidates? Start with your main approach after you’ve described your criteria, and how it maps to them. Which areas does it not perform well in? Search for solutions by calling in help from peers that would tackle those points in a specific other way.

A pitfall here can be to include too many different options as variants. If you have 3 different options and you’ve identified two variants for a component, don’t describe them as 6 permutations. Tackle those as separate decisions or replace some options if the new options perform better on the criteria that matter and as such are ‘strictly better’ than what you currently had described. It’ll otherwise be very difficult to steer a decision between options when you need to mentally map more than a handful of choices.

Depending on your project, you may need to align less or more on the criteria with various stakeholders beforehand and quantify what a High, Low or Medium evaluation would look like. A vendor selection is different from a particular API format, or anything that has impact on multiple teams.

The end approach should be the same: step back to evaluate what criteria matter most, and use that to evaluate the important of a particular pro or con. Get help from others for working out your solutions, and prepare the review session so that the trade-offs are clear and steer the discussion on what matters the most.

Good luck!

Thanks for reading! If you liked this article, you may also like one of the most popular posts: How to make software architecture trade-off decisions or How to get started with Threat Modeling, before you get hacked. or scroll through the history below or on the main page.

Get notified of new posts by subscribing on substack or the RSS feed.