Product Crafter Emilio Carrión

Dependencies are the biggest enemy of delivery

Learn to avoid getting blocked

Dependencies are one of the most problematic obstacles when developing software (like complexity and technical debt). Every time we are blocked by an external agent, another team, or our own colleagues, it causes us to lose focus and detach ourselves from the context. Having dependencies is like encountering a fence that we have to jump in order to continue. And sometimes when jumping we trip and get hurt.

When you have dependencies in your creative process, you run the risk of having blockages. Any case of not being able to continue because “I’m waiting for something” indicates that you could have continued with your work if it weren’t for that dependency, which delays the delivery of new features to our customers.

There are several types of dependencies, between members of our team, with developers of our stack or even with business.

Dependencies between team members

The first dependencies we may encounter are those we have within our own team. Dependencies between development and design, dependencies between backend and frontend, or dependencies even between developers of the same stack.

These dependencies can have many origins, but most of the time they manifest themselves with having to wait for someone to finish something.

If you can’t start developing the website because the design isn’t quite finished, you’re delaying the delivery of the product. If you can’t deploy the client that makes the requests to the backend because the endpoints aren’t finished yet, you’re delaying delivery. If you can’t refactor a piece of code because a colleague is working on that same code and you have to wait to refactor it later, you’re delaying delivery.

Dependencies are not always inevitable and we must try to establish means to be able to overcome them in the best possible way. Like putting a ladder over the fence to jump over it without falling.

Being part of the same team, here the solution is very simple (and essential): communicate.

Most of the blockages and dependencies in a team can be solved just by raising your hand and talking things through:

  • If you want to start developing the product, but the design isn’t finished, talk to the designer to see what things are already clear and what you can start with while they finish the rest.
  • If the backend is still working on the endpoints you need, talk to define a contract that you agree with so that you can start implementing using mocks so that when the endpoints are in place it’s just test and go.
  • If you and a colleague are going to touch the same part of the code and you want to refactor it to continue, talk about it and pair it or think of the best way to do it so that neither of you gets blocked.

Communication, as easy as it is necessary.

Dependencies between members of the same stack

Another type of dependency I’ve seen is that of members of a horizontal (or stack) that belong to different teams.

Team autonomy is essential to scale and develop products in the best possible way, but communication and agreements about how we work within a company are necessary to share learnings and reach common ground that promotes collaboration between different teams.

That’s why it’s common for developers from the same horizontal (frontend, backend, data) to communicate to share experiences, things learned, and mistakes they’d like others not to make.

In some cases I have seen, because there are few members or they do not have peers in their teams, that they review the code among themselves. This is positive, on the one hand, but it can be a problematic dependency on the other.

If there are no more developers from the same stack on the team, it’s interesting for members of other teams specialized in that development branch to review the changes and comment on them. This encourages greater quality criteria and even a reduction of knowledge silos between teams. However, depending on how you implement it, it can be a clear blockage to development.

For example, if we make this review of changes by members of other teams mandatory, what if they’re unavailable? Well, we will get stuck and will cannot continue.

So, how do we get the benefits of peer review if I don’t have anyone from my stack on my team?

There are two important things in these cases: communication and rules. The first of these is obvious, but it is often taken for granted or ignored. If there is good communication with the rest of the members of your horizontal, revisions may not be necessary, since you will share values and a common way of working that will make the development homogeneous in the company.

The latter is necessary when the former is not sufficient to ensure a certain level of quality without causing blockages. Within the autonomy of the teams, there must be certain rules to avoid chaos. The key is to define the minimum number of rules that can be used to guarantee autonomy and to apply them strictly.

In short, talk things through continuously and define guidelines that allow you to work autonomously without getting blocked, but complying with the quality you are looking for. And remember that communication can take many forms, such as regular meetings, pairing, workshops and continuous learning (I emphasize pairing which is wonderful).

Dependencies between different teams

Apart from the dependencies that can arise within your team or between stack mates, there are also other types of dependencies at the organizational level that cause blockages and can cause the development of new functionalities to be affected and delayed.

I’m talking about the dependencies that can arise between different teams in the same company and that often arise from a linear process or needs that one team has over another.

The problem with these types of dependencies is that, unlike those that arise within the team or your horizontal, the different teams that participate in them can have very different objectives. And too many cross-dependencies mean that no one can deliver on their own and people are always waiting for something.

A clear example that I have experienced in my professional environment is when several teams share a waterfall process that generates data that is needed by other teams. For example, in an e-commerce we can find a team that is dedicated to the sales channel and generates the orders that enter the system. Then we can have supply, preparation, and delivery teams that need this information to be able to work. In the same way, these teams that get data from the e-commerce may also generate data that they need from each other, such as the preparation team that requires data on the stock generated by the supply team, or the delivery team that needs to know which orders have been prepared to be delivered.

This situation generates a matrix of dependencies that makes all teams need some data from each other and this can lead to problems when interfaces or data changes according to the needs of each team.

How to solve it? Well, this is where a great communication job comes in again. Agreeing on the contracts and data offered by each team’s public interfaces can mitigate the problem somewhat, however, without continuous communication between the teams disaster is assured.

For other types of blocks, such as one team needing another team to do something, setting expectations is essential. Aligning each team’s needs with each other’s goals will get everyone on board and there will be no frustrations and misunderstandings when one team is blocked by another.

Finally, mention that dependencies between teams can be a smell that the scopes of the teams may be poorly defined. If one team overlaps a lot with the other’s context, dependencies will emerge organically and be difficult to keep at bay. In these cases, reviewing how much of the product and business falls on each team can help solve many of these problems.

Dependencies with business or third parties

The last type of dependency that I am going to comment on is the one that is generated with the business or with third parties such as external services or even the state.

It is often the case that certain parts of the product or development are affected by decisions that have not yet been made. The business is deliberating whether the change goes forward or not, there is a law that they are about to pass, but it is not final yet, our search provider will change the conditions and it will not fit our use case anymore.

Events and decisions that are in the air and that generate uncertainty that prevents development from flowing in a correct way.

In these cases, it’s best to unlock the already decided parts to keep learning and iterating, and keep the options open for when the decisions that need to be made are made.

Again (and I know I’m repeating myself, but it’s very important), in these cases communication is essential (although sometimes with entities such as the state it’s not entirely viable). If we do a good job of setting expectations with business and third-party services, it will be easier to move forward when the uncertainty disappears.


Dependencies represent a big challenge to efficient software delivery. These obstacles, whether within the team, between members of the same stack, between different teams, or with external factors such as the business or third parties, can lead to significant delays in delivering functionality to customers.

Continuous communication stands as the fundamental tool to mitigate these blockages, as it allows agreements to be established, lessons learned to be shared, and possible obstacles to be anticipated. Team autonomy is essential, but it must be accompanied by minimum rules to avoid chaos. In addition, peer review, clear contract definition, and careful alignment of goals across teams are key practices.

Ultimately, effective dependency resolution involves not only getting around fences, but also building strong bridges of communication and collaboration between everyone involved in the development process.