How the Theory of Constraints can help you manage bottleneck in your software delivery process

Lubo Drobny
Slido developers blog
7 min readOct 8, 2018

One of the challenges growing software engineering teams often face is that one person in the team who created everything at the start becomes the bottleneck for the whole team.

The Theory of Constraints is a useful tool that can explain why this happens. If used well, it can help you improve your day-to-day work.

In this article, I’ll explain the theory using a simple example and tell you the story of how we addressed this issue in our team.

The Theory of Constraints

The theory is simple: There is always one bottleneck in the system that limits the system’s output. As a consequence, it significantly affects the system’s ability to achieve its goal.

To give you a practical example to put the ToC in context, consider this situation:

My wife does the laundry every week. As we’re a big family, it takes her 17 hours (2 days). She wanted to finish it in 11 hours (1 day) so she asked me for help.

I took a risk and explained to her that my help wouldn’t help her achieve this goal due to the ToC.

Applying the ToC to this scenario, here is my analysis:

This is what the system looks like

The total time is 17 hours but the goal is to do it in 11 hours. My calculations tell me that:

  1. Washing takes 1.5h
  2. Drying takes 3h
  3. Folding takes 0.5h

Before diving into possible solutions, here are a few questions to help us understand the system better:

  • Where is the To Do queue? Washing.
  • Where is the Work In Progress queue? Drying and Folding.
  • Which resources are usually idle during the process? Folding and Washing.
  • Would it help if I found a way to fold clothes faster? With my help, we can shorten folding time to 0.25h, but the overall time would still be 16.75h. (Yeah, I told you so.)
  • Would it help if I found a way to wash clothes faster? Of course not. It will still wait in queue for drying.
  • Would it help if I found a way to dry clothes faster? -> Yes. If we use a higher speed of centrifugation drying time would only take 2.5h and overall time would decrease to 14.5h. That is still far from our goal. When we combine it with my help with folding we could reach 14.25h. While that’s better, we still have not reached our goal, but at least I’ll look busy and engaged.
  • So, where is the bottleneck? Obviously, it’s in the drying part. We would definitely need a second drying machine to achieve an overall time of 11h.

Also, other questions popped up in my mind:

  • What happens when I find a pair of socks while the washing is in progress? Since they’re small, I can put it into the next round or stop the machine and put it in the current load.
  • What happens when I find something bigger, like a blanket? Since it’s big and will probably not fit into the next round, I’ll have to add an extra round and prolong the overall time.
  • Will the bottleneck stay the same if we have another goal, e.g. to do the laundry in an eco friendly way? No. In this case, I will have to address the chemicals I use for washing.

What does this example tell us?

1. The actions taken after the bottleneck point do not bring significant improvement towards our goal.

2. If we improve the quality of input into the bottleneck, we are able to achieve some improvement and get closer to our goal.

3. Random improvements in the system that are unrelated to the bottleneck do not help much. If people look busier and engaged, it does not mean we are reaching our goal. In fact, it could be the exact opposite.

4. Small batches can go through the system more easily, unlike big ones.

5. Different goals can have different bottlenecks.

How our engineering team resolved the bottleneck issue

Taking this simple example a step further, let’s explore the theory in a more complex system such as Software Development:

Our goal is to deliver high-quality, easy-to-use product features as soon as possible to help our clients get the best results. All this while learning and developing our skills and habits in order to improve and adapt over time.

For the purposes of this article, I will focus solely on the first part.

We can identify a few typical phases that engineering teams go through to deliver the product features (roadmap):

  1. Preparing the technical specification
  2. Sprint grooming
  3. Coding
  4. Code review
  5. Testing
  6. Deployment into the production
  7. Collecting feedback and data

At the first glance, you might consider measuring each phase like I did in my laundry system. But this system is much more complex and less straightforward, as hidden dependencies and accidental complexities that come into play.

What’s more, the phases overlap widely, the borders between them are often blurred, and there can be unexpected loops between them.

Therefore the system varies and predictability is very low. You can measure it, identify the bottleneck (with some probability) and do some action, but you cannot predict it just by analyzing phases and ‘to do time’.

To put this in context, here is an example from our own backyard:

In the beginning, there was a single developer at Slido who did everything. As the team grew, we came to a point when the team delivered features not sooner but later.

How is this possible?

The hidden dependency on one developer meant that almost all features created by other developers had to go through this one person due to his unique knowledge about our API and infrastructure. But he was not able to handle the increasing workload at the speed we needed.

He became a BOTTLENECK.

To address this, he delegated more of his tasks to other team members and more developers started to learn and develop API for their teams.

It worked for a few months. However, over time our feature delivery was delayed again. The problem from API coding was moved to the next stage of the process to code review and code merging into production where this one developer was heavily involved.

Our solution:

1. We switched into extreme Kanban for him to prioritize his work on a weekly and sometimes daily basis to avoid random/unplanned/low-prio work

2. We delegated all the tasks we could to achieve more flexibility.

3. We tried to keep the size of merged code small and clean so that merging and review could be done quickly (we improved the quality of input into the bottleneck and used small batches)

4. We limited the number of features developed by others teams that depended on the bottleneck (we preferred those features which were doable by the teams themselves)

If you have read the book Phoenix Project, you might recall a character named Brent who was involved in every project and became a bottleneck for the whole team. We, too, faced a similar situation. But the bottleneck doesn’t always have to be a person. It can be a technology, process, structure or something else.

To help you avoid a similar situation, here are my six tips based on the ToC principles:

  1. Draw a big picture of the system
    Local optimization is a waste of time and random improvements without understanding the system are just a guessing game.
  2. Describe the goal of the system and the way you can measure it clearly
    Do you want deliver sooner or do you need an optimal workload (e.g. 0% developer’s idle time)? These are not the same goals so the bottleneck is not the same in these cases.
  3. Find the bottleneck
    It’s usually a heavily overloaded resource with a big upfront queue and an idle (waiting) downstream.
  4. Focus on the bottleneck
    a) Visualize work through (e.g. use a Kanban board).
    b) Remove any non-productive work, avoid distractions and task-switching.
    c) Ensure there is always something to work on so that the bottleneck is never idle (create a buffer of work before the bottleneck).
    d) But don’t overload the bottleneck with too much work in progress: let the bottleneck “pull” work from the buffer.
    e) Carefully prioritize what the bottleneck works on, preferably a small batch.
    f) Everyone else should work at the rhythm indicated by the bottleneck.
    g) Ensure that the bottleneck only receives the highest quality input.
    h) Ensure that all outputs of the bottleneck are treated carefully, so they’re not wasted.
  5. Invest in improvements
    Now you can think about hiring more people or buying new technology, Simply throw more money into the system.
  6. Go back to number 3 until you reach the goal

Wrap up

Using the above tips, you can work on improvements in step-by-step cycles. Any time the bottleneck is moved you have to take appropriate actions in order to achieve your goal.

But what can you do if there is no real chance to resolve the bottleneck but you still want to reach the goal? In such cases, I can see only one way out:

CHANGE THE WHOLE SYSTEM

--

--