product development Blog

3 months ago

Every feature considered harmful: Debts in software development

We tend to believe that every new feature is a good and valuable addition to a product. Quite often, it can be hard to not implement a feature, especially when you’re constantly hearing good ideas for new features every week.

The problem is that every new feature adds debt or creates a placeholder for future debt. You deliver more and more features, accumulating more and more debt. Most people don’t know how to work with debts. I don’t. Everyone knows about technical debt, but there are few more types of debt in software development:

  • Functional debt. The needs of users are changing, but the system forces them to follow old flows, and doesn’t cover new cases.
  • UI debt. Over time, the user interface can lose consistency and coherency, making the system harder to learn and understand
  • Quality debt. Bugs are ignored, the system shows unpredictable behavior, experiences errors, crashes
  • Technical debt. Architecture and code quality slows down development.

Any new feature in a product may become a source of all these kinds of debt.

Functional: Feature solves some problem. The problem’s definition may slightly change in the future, so feature functionality must adapt.All teams estimated work in hours, but then estimation in abstract points became popular. This new need demands changes in a product to support points as an estimation unit.
UI: A new feature quite often introduces new patterns and new UI elements.Designer decides to add new type of lookup field for some feature. This lookup is used in a single place and makes the whole UI less consistent.
Quality: A new feature almost inevitably adds new bugs. In complex systems, bugs may affect many other features.Live Update functionality affects many areas of a system. Bugs in unexpected places will follow.
Technical: Technical implementation of a new feature is almost always not ideal. It may cause existing system modifications that are not optimal, and side effects may be severe in the worst cases.Under time pressure, you implemented a quick solution for UI extensions via Mashups. It does provide great flexibility, but is very fragile. Any change in HTML or CSS can break some extensions. With time, many mashups are created and changes of this mechanism will be hard.

The image below shows several features in a product. Every feature adds some debts. In reality, it is extremely hard to add a feature with zero current and future debt.

features debts

Every Feature needs maintenance: functional, UI, quality, technical, documentation, localization. What if you have 100 features in a product? What about 1000? Can your software read emails already?

New Feature vs. Debt Payment

When should you add a new feature, and when should you pay back some debts? Let’s check the product lifecycle. Imagine you are running a very young startup. You don’t care about debts at this stage. You care about market expansion, new features, and growth. Now imagine the product is dying, it is too late to focus on debts, it’s over.

product lifecycle and debts

It seems the right time to focus on debts is when a product has proven its success on the market and is about to enter the “mature” phase. For a typical SaaS B2B product, this may be after 4-8 years. The chart above is valid for our SaaS product, Targetprocess. In my opinion, we started to focus on debts about 2-3 years late. We're finally coming over the hill, but it will take some more time to re-energize development.

Ideally, some part of your resources should be dedicated to debt payment at all times, but after 6-8 years it may even be a good idea to have a “Debt Return Year” or something. At this point, development speed decreases due to technical problems: UI consistency degrades, many features are outdated, bugs and performance issues annoy customers.

Moreover, you’ve accumulated enough customer feedback and now understand your domain much better. Mistakes you made and new opportunities became more clear. You need an ultimate clean-up to prepare a launching pad for a powerful push.

It is extremely hard to slow down and clean up the mess in a product. You are always afraid to lose market share and functional edge. I don’t want to be extreme here, just want you to think about every new feature you add from a debt perspective.

What to do?

There are several obvious consequences.

  • Build small systems. If you need a large system, build several small composable systems.
  • Less features -> less debts. Someone asks for a new feature? Default answer is “No”.
  • Modularization is desired, since you can re-write modules to pay back debts and reduce side-effects. This means you can have more features in a modular system with the same level of debt as in a non-modular system.
  • Remove rarely used features. When you remove a feature, you remove all related debts.

I want to finalize my post with a quote:

One thing that UNIX does not need is more features. It is successful in part because it has a small number of good ideas that work well together. Merely adding features does not make it easier for users to do things it just makes the manual thicker. The right solution in the right place is always more effective than haphazard hacking. — Rob Pike & Brian W. Kernighan

4 months ago

Service Desk: localization and other improvements

Hi all!

It's been a while since we posted something new about Service Desk, and I am happy to share the latest changes with you.


Service Desk is now fully translated to 10 languages, all thanks to a number of awesome people who volunteered to contribute to the translation process. This is really impressive, as we did not have the chance to hire translation agencies for this feature. Such support from the community is really appreciated and makes us feel that maybe we did one or two things right.


The following languages are now available:

  • Dutch
  • French
  • German
  • Hungarian
  • Italian
  • Norwegian
  • Polish
  • Portuguese (Brazil)
  • Russian
  • Spanish

There is a global, default language which be set at Service Desk options by an admin, but users can select the one they individually prefer in their personal settings. This will be useful if you have people working in different locations.

New Search

It's no secret that search functionality was rather... limited in Service Desk. Basically, it searched for the exact phrase you typed, and it was rather slow. We did this on purpose back then, since we planned on reusing the awesome new search engine being developed for Targetprocess. This engine is now available in Targetprocess, and you can already find it at our own instance of Service Desk. It will be available for all Service Desk users with our next release (v.3.12.3).

Widget Builder

As you may know, you can embed a simple Widget into any page or application so that users can submit requests right from there, without using the full version of Service Desk. This is not something really new — it was already available in previous versions. However, it was not very convenient to configure it, as you would almost certainly need to consult our guide and form your Widget link by adding parameters manually. We simplified the process by allowing you to configure your Widget at Service Desk Settings:


Improvements in permissions

  • Targetprocess administrators will now see private requests in Service Desk, as they would in Targetprocess.
  • Request owners can see their own private requests even if they are not among requesters anymore.
  • If you are a requester or the owner of a request, you can now see the request in the My Requests list, even if the project is not available in Service Desk. This will help companies who have one project for incoming support tickets, and then distribute requests to the appropriate project by Support Team. In fact, this was the only thing preventing us from deprecating the old Help Desk portal where such a scenario was both supported and critical for some customers.

Usability improvements

  • It is now much easier to find the My Requests list, which was previously hidden under the cogwheel icon.
  • Targetprocess users will now see internal links to Targetprocess for requests and related items.
  • We are no longer displaying states in groups (like Open, In Progress, Done) if the projects use only one process. In this case, you will now see your actual states.
  • It is now more clear which request type is currently selected.

There were some other minor bug fixes and smaller improvements as well, such as the addition of my personal favorite black color theme.

We hope you like our Service Desk, and we'd really love to hear your thoughts and feedback.

Have a great weekend everyone!


6 months ago

Visual Reports Editor: Beta of cumulative, burn up & down reports

We are happy to announce the beta release of historical reports for all On-Demand accounts (with the exception of private clouds, for now).

You can see the basics of how to start using it in the image below.


A full explanation on how to use historical reports can be found in our guide article: How to create a historical report

We will really appreciate your feedback on this beta release of historical reports. What do you like about it? What could be improved? Let us know what you think at

7 months ago

Capacity Calculation

Capacity calculation: highly anticipated and finally here! From now on, you can calculate the capacity of each user while planning Releases, Iterations, and Team Iterations. Finally, you will be able to see if a user is overloaded with tasks, or if they can take on more work in this particular iteration.

This will make it so much easier to plan your resources across one or many projects. We didn't forget those who work part-time, or those who are allocated by n% of their time for a particular project and period of time.

Available capacity will be summarized across one or many projects based on:

  • Work days in a “work container” (Release/Iterations/Team Iteration)
  • Weekly available hours by user
  • User allocations, if there are any

Capacity can be calculated for User Stories, Bugs, Tasks and Test Plan Runs. It also works for Initial Estimates for Features and Epics if there are no child entities. In other cases, they will be estimated by the sum of child entities’ effort.

Please keep in mind that effort from Tasks is not included in User Story effort for capacity calculations.

Let’s dig into a few cases and see what it looks like.

Case 1: One Project, no Allocations

This is the easiest way to plan resources if you have one project and don't use allocations.

On Boards where you see cards grouped by users and Releases/Iterations/Team Iterations, you will notice a small box in the right corner of a cell. It shows the assigned effort and capacity of a person:


When you move cards from the Backlog to a Release, the values for assigned effort and capacity are updated:


Based on weekly available hours, we know that John works full-time, 8 hours each day. In August, we have 23 work days, so John’s capacity for July’s Release is 23*8, which equals 184 hours. When we assign a card to John, the system calculates assigned effort and compares it with available capacity.

On the next screen, you can see that John is overloaded for August's Release by 4 hours. It’s already easy to notice whether there is some spare capacity or an overhead. Cells with spare capacity are highlighted green, and cells with overhead are highlighted red.

To check the details of assigned effort and capacity, just hover your mouse over the tooltip in the right corner of a cell:


If some supported cards are not being displayed on a board (perhaps there are some filters applied), and there is some hidden work assigned to you, the cell will show the aggregate sum of all assigned effort, including hidden cards.


If you use points for estimation, you will be able to see the sum of assigned effort for a user in a particular Release/Iteration/Team Iteration, but not the capacity

Case 2: One Project + Allocations

Let’s dig into a case with more than one Project and user Allocations.

John will be allocated to Project Irol System for 40% of his hours, and to Mobile Platforms for 60%.


The John’s capacity for July for Irol System Project was immediately updated, 40% from 184 hours equals 73.6 h



If at least one of the users is allocated to a Project you should allocate others as well. Otherwise their capacity will be calculated on assumption that their allocation is 0%

Case 3: More than one Project + Allocations

Let’s now plan a Cross-Project Release (the scope can include work from one or more projects).

John’s allocations mean that he can dedicate 73.6 hours to Irol System and 110.4 hours to Mobile Platforms (40% and 60% accordingly):


You can click on a few cards and see the sum of their effort. This is especially convenient when moving a few stories from the backlog!


If you have more than 500 cards in one cell, Effort will be calculated by the first 500.

If you estimate work entities in points, capacity will not be updated. Capacity is calculated in hours only.

Case 4: Team Iterations

As you know, Teams and Team Iterations can be assigned to multiple Projects. Just keep in mind that Capacity and Assigned effort will be calculated based on work that is included in a particular Team Iteration, not based on all Projects to which a Team is assigned.


When Releases/Iterations/Team Iterations begin, their capacity value will be regularly updated based on the remaining amount of work days