Assess, Adapt and Evolve: How Mobile @ Hootsuite strategically tackles technical debt

Prashant Bhargava
Hootsuite Engineering
9 min readAug 17, 2023

The only way to go fast is to go well. - Uncle Bob Martin

Technical debt constitutes an essential part of any software system. In the short term, it enables faster development & delivery of a product, particularly when you are still ideating or searching for the right product-market fit. However, in the long term, accumulating technical debt and failing to repay it can slow down any team of professionals.

In this blog post, we go through an approach that the mobile team at Hootsuite has taken to continuously tackle tech debt and evolve our architecture. This, however, is separate from the general principle of leaving the code better than you found it, since that always needs to be the case, without any exception! What we discuss here are initiatives that require significant investment or dedicated resources for at least a couple sprints.

Before we go into details, I want to also highlight that Technical Debt is not just code complexity or code rot, there are several aspects to it that need to be considered. Here’s a list of types of debt from Martin Fowler’s blog post about bottlenecks of scaleups (technical debt being one):

  • Code Quality
  • Testing
  • Coupling
  • Low Value Features
  • Outdated Frameworks
  • Tooling
  • Reliability & Performance
  • Automation
  • Deployments
  • Knowledge Sharing

It’s also important to acknowledge that not all types of technical debt require immediate attention.

Example: Imagine a class spanning a few hundred lines of code written by an engineer who left the company long before you joined. This class does some complex synchronization task and is difficult to understand but does its job meticulously. It has had no bugs in the past 1–2 years and the performance has been good, without needing any maintenance. You feel like refactoring it will be a good idea since it is too complex and can be made simple. Here are some potential questions & their response that I have experienced quite frequently, that have helped me decide if such a class needs refactoring:

  • Will refactoring it, likely help in better understanding of the code? Yes!
  • Will making it easy to read make it easy to maintain? Probably yes!
  • Will refactoring it make it easy to test? Absolutely!
  • Great! So how will the product/business do better once we finish refactoring it? Ummm, what do you mean, I am not really sure.

So, the question to ask yourself is: What value does the refactor provide to your team, and what value does it provide to the product and thus business?

Since this class works perfectly fine and hasn’t been touched in the last 1–2 years, the probability is that it will not require any changes in the near future. Therefore, the business value that the refactoring will provide is zero. To be honest, the ROI on it could actually be negative because, by refactoring, we are taking on the risk that the new refactored version might not work as perfectly as the old system. In fact, the refactoring might introduce potential new bugs.

This is exactly why addressing technical debt strategically is so important. It cannot be addressed ad-hoc or just-in-time when you are ready to work on a new feature. This is because, not only could it increase the scope of the feature and add risk to it, but also, there can be other areas that need urgent attention that have nothing to do with the feature itself. For example: a critical microservice that frequently fails, but has no involvement in the new product initiative being developed.

Understanding the criticality, identifying the pros and cons will help you in understanding the value of addressing a particular technical debt and allow you to pick your battles meaningfully.

And this is the practice that the Mobile Team at Hootsuite has adopted over the past few years. Let’s go over how we use the Assess, Adapt & Evolve strategy to counter technical debt.

Step 1: Assess

In order to begin remediating any kind of technical debt, we need an honest assessment of the current state of things. This should include not only the pain points or weaknesses, but also strengths and positive aspects as it not only ensures that we do not lose sight of things that work for our team but also keeps the team morale high.

1.1 Understanding the current state

In our team, we collectively do a retrospective of our technology stack, current debt, existing strategies and development processes on a shared Trello board. This has numerous benefits, as it promotes transparency, encourages collaboration, participation & open communication. It also serves as a centralized repository of information thus aiding in decision-making and facilitates root cause analysis. When team members see their input and efforts acknowledged and acted upon, it boosts morale and fosters a sense of ownership and empowerment within the team.

1.2 Evaluating the impact

We then go through each of these items to understand how it impacts development speed, product quality, and overall team productivity. I would encourage you to gather relevant data to back your analysis. For example, just “feeling” that the code has too many hard to reproduce bugs is not enough. Try to back it up by finding the Reproducibility Rate from JIRA. Similarly, for defects or incidents, take a look at MTTD & MTTR metrics and get a quantifiable number that can back your feelings. Other metrics like cyclomatic complexity (to measure branches in code), average PR review time (to measure bottlenecks in code review) can help you understand the criticality of the issue and take incremental steps to address it.

Step 2: Adapt

After assessing the current state, now is the time to adapt your findings into an actionable strategy. This involves taking a holistic view of areas that require your attention and formulating an actionable plan of attack. Don’t forget to identify and involve stakeholders at every step, since gathering as many POVs as possible will help your team in developing the right strategy.

2.1 Identifying Themes

Once we have had a chance to assess different aspects of our technical stack, we group them based on the domain they impact. These domains or themes can be different for different teams and it is not possible to define an exhaustive list.

As an example, while analyzing the findings of the retrospective, we realized that there were a lot of initiatives where we knew what the problem was, but were not sure how it impacted us or what should be our pathway to address it. In order to address each of these deterrents, we needed to answer 3 basic questions:

  • What do we want to do?
  • Why do we want to do it?
  • and how are we going to implement it?

Unless we made time for our team to answer these 3 questions, these problems would have remained vague and continue to impact us. To address this, we identified a “Process” theme where such initiatives belong and every quarter we try to iterate on 1 or 2 such issues.

👏 Before going further, pat yourself on the back! Things are looking really good! You are starting to make sense out of your technical debt. You have a fair idea of what your priorities should be, you have data to back it up and you are starting to think strategically about the initiatives.

2.2 Defining Key Results

This is the right time to ask yourself a few questions:

  • What are you looking to achieve out of this strategy?
  • How do you measure success?

Yes, I am talking about OKRs.

OKR is like a special plan that helps you know what you want to do and the steps to do it, just like a treasure map for reaching your goals! — ChatGPT, prompt “Explain OKR to me in a single line as if I were a 3 year old”

Look at the areas of strengths and weaknesses and define Objectives & a set of Key Results that would help you measure the outcome that you want to achieve. For example: If your objective is to “Improve the durability of the app” because there are too many crashes, you may define a Key Result of “Reduce the total number of crashes by, say, X%”.

2.3 Creating a Technical Roadmap

Now that you have defined the outcomes of your strategy, backtrack to Step 1 and sort the work items based on their urgency and potential impact on the product. Develop a roadmap that outlines the sequence of tackling these work items after considering dependencies and plan an order that optimizes development efforts.

At Hootsuite we use a modified version of the RICE framework for technical projects, to measure its priority and impact. Spoiler alert, use these prioritization metrics with a grain of salt. Unfortunately, there is no one solution that fits all. Hence, at the end of the day, your team should be the one responsible for prioritizing these items rather than relying solely on a framework.

Step 3: Evolve

The last step focuses on making sure we are constantly iterating and adjusting our strategic approach to address technical debt. What you need is a mechanism to facilitate conversations, incorporate feedback and make space for new concerns as the old ones become obsolete or get addressed.

3.1 Execution

Next comes allocating resources, executing the roadmap and balancing it with any new feature development. We divide our capacity every quarter between a healthy mix of feature development, technical projects and bugs, thus making progress on all the fronts. This ratio can go up and down based on business priorities or other unavoidable circumstances, but nonetheless we make every effort to make sure we are iterating on our technical goals every quarter.

3.2 Iterative Improvements

Schedule regular sync meetings to track the progress of your technical strategy. It can be a quick 5 min check up on the things that have been prioritized and are being executed. The mobile team does a monthly meeting on our Kanban board to go over all the In Progress items and discuss & prioritize updates or any new agenda items that may have come up. This also helps avoid accumulating new technical debt and encourages a more proactive development approach.

Additionally, don’t forget to share & reflect on how you are making progress with the execution of technical strategy and whether it is helping address the technical debt. Remember it’s important to gather feedback from the team as well as the stakeholders. On Mobile, we do quarterly State of The Union meetings to share the progress of all our initiatives to senior leadership. This fosters a sense of ownership and pride as well as creates visibility into all the awesome work that we have been doing.

3.3 Be Flexible

Remember, the strategy needs to work for you, not the other way around. While you need to ruthlessly prioritize and limit your focus to a few key projects. you need to also be prepared to adapt the technical strategy as the organization’s needs change or new technical debt items emerge. Evolution is essential to maintain the relevance and effectiveness of the strategy over time.

In conclusion, strategically addressing technical debt is vital for efficient software development. The mobile team at Hootsuite exemplifies the “Assess, Adapt & Evolve” approach, prioritizing impact, involving stakeholders, and maintaining flexibility. By shifting perspectives, identifying and assessing technical debt, strategically planning growth initiatives, fostering collaboration, and embracing continuous learning and improvement, we transform technical debt from a burden to a catalyst for growth.

The Big Question:

How can we say that this framework actually works?

Well, for one, our team is on the second iteration of this framework! Having completed one full cycle successfully, we wanted to share what we have learned so far and gather feedback. We went from identifying our pain points, comparing our metrics with industry standards, to iteratively making improvements, until the very pain that plagued us has now become one of our core strengths!

Interested in learning what exactly we did? Well, that’s a story I might just have to share in another writeup! In the meantime, keep an eye out for more exciting updates from our team. 🦉

--

--