Saleswhale Blog

Balancing User Impact and Tech Debt in Feature Development (from an engineer’s perspective)

Written by Lim Ken Jyi | 02 December 2021

User impact and tech debt have an interesting relationship: we want to build features that bring value to users when they use our product, but we also have to watch out for the costs in tech debt that can result when we build. One of the more important (and difficult) parts of our job scope involve balancing user impact and tech debt when we build features.

In case you are unfamiliar with tech debt, it's what accumulates when we use short-term technical solutions to quickly deliver features or to resolve customer issues. I say short-term here, as these solutions are usually unscalable and need revisiting for further development.

As an agile startup, we are not exempt from this either. We've had growing pains in the past year balancing quick fixes vs. building a long term scalable solution.

In the course of building our integrations, we’ve had to contend with tech debt in the form of a separate microservice with leaking concerns in our main service. This has caused a fair bit of development pain while we’ve tried to extend our integration features. The general consensus now is that we’ll need to do an eventual merging of the two services to correct this.

To avoid similar situations from happening again, I’ve been trying to be more mindful during our weekly sprint meetings. “How can we make this particular detail work? What impact will this feature have? How much tech debt will this approach generate?”

To show how things usually go, here’s a wizard and his product manager from Magic’r’us working on magic circles:

Focusing on user needs

Before we go ahead with trying to make a triangle with five sides, it’s a good idea to try and understand why we need this feature in the first place.

The focus here is not on trying to avoid building, but to figure out if there’s an alternative strategy that satisfies the user’s needs while making the feature more manageable (and thereby cutting tech debt).

This is generally a back and forth process, where members of the product team will throw out suggestions. We then start spiking on potential approaches and listing out the pros and cons. The process can get quite involved, with the suggestions being tested against users to verify if their needs were being met with these alternatives.

Using this process, we’ve managed to scope down larger features. One such feature was enhancing our Salesforce integration to allow the syncing of campaign information from Saleswhale back to Salesforce.

While we saw this as an opportunity to sync up our internal campaigns to Salesforce Campaigns, upon further research we found that the user needed only certain campaign-relevant components for attribution and easier classification of their leads. This allowed us to scope down the feature to only syncing individual fields with campaign information back to their Leads and Contacts.

This afforded several benefits: we were able to delay the evaluation of whether the concept of a Campaign in Saleswhale was a good fit for a Campaign in Salesforce (which would have required more resources and user data) without affecting user impact, while lowering the amount of effort required to develop real-time sync in favor of a push when campaign state changed.

Raising potential tech debt concerns

More often than not, innovative approaches and ideas come at the cost of some form of tech debt. It’s important to provide visibility on these trade-offs to the team at large, so that we can evaluate the impact relative to the debt incurred when choosing an approach.

We’re looking to maximize the amount of impact we can generate for the debt we take on. This decision becomes easy when we know that:

  • Taking on the debt allows us to quickly generate large amounts of value/impact to the user
  • The onboarded debt is either easy to resolve or has a long window to collection

Cases that fall into the green and red zones above are usually pretty obvious (with a few exceptions), with yellow and orange being a little harder to determine. The majority of the debt that tends to snowball usually comes from the yellow zone. General gotchas that we’ve run into here are:

  • Misclassifying yellow cases into green (good spikes are important!)
  • Misclassifying red cases as yellow (the absolute worst; always test prototypes with users!)
  • Repeatedly taking on features in yellow without resolving the accumulating debt (more on that later)

A good example of a feature that falls into the green zone would be when we needed to support PersonAccount information from Salesforce. We onboarded tech debt (by converting Account -> PersonAccount before hitting Salesforce APIs instead of tracking the Account status within our systems) to quickly release the feature.

This approach had clear immediate value (we were able to immediately sign on 2 customers who were waiting for that functionality to annual contracts) with a long window to collection (we didn’t need to build any features on top of PersonAccount support for at least the next six months, plus there was a chance we would be relooking our integrations as a whole).

Unfortunately, clear-cut solutions like these aren’t always common. A more debatable example of debt (one that we thought was green, but was actually a yellow) we took on was the modeling of our draft campaigns as a new model instead of as a state of our existing campaigns.

We could quickly implement campaign drafts for our users without breaking existing processes that were reliant on campaign states. However, the draft feature ended up being a foundational block that would eventually support many more sub-features.

While the immediate value here was clear (and quite substantial – the feature is still being used daily by hundreds of our clients), the debt has also been significantly more difficult to resolve. Efforts to resolve drift and merge the draft with the main campaign are still ongoing, a year down the road (partially thanks to the fact that the difference in model was propagated all the way down to our API layer).

In each case, we try to extract learning points (similar to the breakdown I just did) and factor them in as considerations for new upcoming features. Ultimately, evaluating these trade-offs is something that comes with experience; making mistakes is a natural part of figuring things out.

Managing tech debt

Like all other forms of debt, tech debt eventually has to be repaid. If debt accumulates without being tackled, development speed for newer features gets slower as the codebase gets more and more tangled. When necessary, we try to communicate that time is needed to tackle outstanding debt after a feature has been released or during lulls in the development cycle.

Some strategies we’ve tried include:

  • Designating a mandatory cooldown week for repaying debt after the launch of certain features
  • Allocating some days to reducing debt during the feature development period itself if the existing feature requires less resources
  • Deprioritizing low-impact follow-up features to extend the time before the debt has to be repaid
  • Holding department-wide idea jams to figure out alternative solutions to reducing the debt

The first two are pretty complementary: if we can’t finish refactoring within the cooldown week, we often try to get time during the next feature by tackling lighter high priority features first.

I’ve found that deprioritizing low-impact follow-up features also has an additional benefit: it gives us more time to track user response to the initial feature to give us a better idea of what to build.

Summary

Jokes aside, a big part of the fun in product development comes from brainstorming together with designers and managers on new ways to deliver features within time and resource constraints.

One great thing about working in an agile environment as an engineer is that you get to experience implementing under a diverse range of conditions; from fast and scrappy to get working code out the door, to coming back and optimizing for performance when user needs dictate and time affords.

If that didn’t scare you off, we’re looking for candidates who’re interested in building (both our product and our culture) together with us. If you’re interested in making an impact as a product engineer, product manager, or product designer at Saleswhale, we’d love to talk to you. Just send us a message on the intercom! (The little button down by the right.)