Work in progress

A just-in-time process has one tricky aspect: limiting work in progress (WIP for the rest of the chapter).

First of all, a just-in-time process can't properly function if everyone is working on something new at the same time. Because if that's the case, then there is no one left to move anything else forward in the workflow. Pay attention to the dynamics a just-in-time workflow generates. We get excited for new things, and it's natural to want to start working on a new feature as soon as we run out of work. This leads to those "there is too much going on" conversations we all have had. To avoid "being busy being busy" congestions in the workflow, teams need to do less. It's hard to see because it's a bit counterintuitive: when "there is too much going on" everything feels already slow, so how come doing less would help? The answer is that context switching costs time but that cost is hard to visualise.

"There is too much going on" means there are too many unshipped features. The team goes back and forth between too many things, so nothing moves forward fast enough:

Context switches have a cost that's proportional to the size of your WIP. The higher your WIP, the more context switches occur.

In the ideal scenario, at least one person is available at any point in time to do the next thing (this doesn't mean they just pick up the next feature). For example, if you have a team of four people, ideally there are no more than three things going on. The question is: how do you ensure WIP is always respected? Answering this question is hard, making everyone understand WIP limits is very challenging, and you can't assume everyone is even aware of the problem. Some tools let you set WIP limits at stage level (they often call stages columns nowadays), but that doesn't solve the problem. It's only an annoying visual clue, something has already gone wrong.

The best way to solve a problem is preventing it from happening, and it's possible to do so with WIP limits. A just-in-time workflow needs constraints to limit WIP. Here's an example of a constraint: some actions can be performed only in a specific order. As this is too abstract, let me provide you with a real-world example from my past experience.

The following constraint assumes everyone can pick up a feature from every stage in your process (reinforcing the idea that there are "no privileges, no elites"). Here are the rules:

  • A team member can't pick up a new story if they don't "push something down to the next stage". In other words, they can't pick up a new story if they don't contribute to moving things in the workflow first.
  • No one pushes work they produced on their own down to the next stage. For example, if someone developed a feature, they can't ship it to a further stage.

The combination of these two rules creates a constraint that auto-limits the workflow. If these two rules are never broken, team members pick new features when that's the only thing they can do. Picking up something new becomes a special moment because it doesn't happen so often any more and it's the perfect time to play the estimation game. While in Estimation, I make the argument of focusing on breaking down features into the smallest possible diffs, I still see value in the estimation process itself. Assuming t-shirt size for effort, my reasons are the following:

  • Common understanding

    If one developer estimates a feature as S and another as XL, chances are at least one of them didn't understand the requirements. You can think of estimation as a ritual that gives people a chance to clarify misunderstanding before the work starts.

  • Data, data, data

    The data collected with estimations provides insights and correlations that help you "stay kaizen" over time. If you have the data, you can look for correlations. For example, you can check if there is any correlation between the size of features shipped and bugs. A great exercise.

  • Keep WIP in check

    Once a team runs into too much WIP a few times, people start seeing patterns that lead to the unpleasant "there is too much going on, nothing happens". Estimation helps anticipate the situations in which rules break and conversations like "You know, I wouldn't start this feature now. There are a lot of things we can test or review" happen often. That's a fantastic way for a team to auto-regulate WIP.

Estimates have a bad reputation because they are never accurate, so putting effort into coming up with numbers seems like a waste of time. The underlining assumption is that you can't estimate a project properly. This is when self-limiting WIP is so important, it's the core of the conversation about a "just-in -time to do, doing, done" workflow. Now let me recap what we discussed so far:

  • You simplify your workflow as much as you can.
  • You estimate work anyway, even if you don't share it.
  • You have a self-limiting WIP.

If you analyse the data of such a process, you find a strong correlation between the story size and the efficiency of the overall process. Specifically, the smaller the average story, the more efficient the process. The reason seems obvious without data too: smaller chunks of work get completed faster, they are easier to review, ship, and test. Putting together the three ingredients and the fact that smaller stories are better is key to accuracy. I like to sum it up this way:

If all we do takes half a day, we only need to know how many things we have to do in order to know when we complete a specific project.

The assumption is strong: everything you do can be broken down into the smallest units of work possible. The benefit is equally strong: you can literally say in which day of the month you will be able to ship a non-trivial feature.

In Communication, I mentioned that you should strive for the smallest backlog possible, but not smaller. Let me expand on that.

A small backlog communicates well the idea that "this is what comes next". As it often happens, good communication has good side-effects. Making the backlog as small as possible but not smaller makes you see that stage starvation is beneficial.

Usually the development workflow is a pipeline in which you push things from left to right. A good just-in-time workflow works the other way around: work is pulled from a previous stage once a given stage starves for more work. It seems like a semantic difference between pushing and pulling work, but it's much deeper than that. Starving stages start with starving the "to do" stage which means work doesn't pile up. The less work there is to do, the less risks come out of something else going wrong. When some work goes wrong, it travels back to the previous stages of the process. This hurts the effort you put into limiting work in progress. By definition, you can't predict unexpected problems so you can't build a workflow that auto regulates its WIP from the perspective of the backlog. You want to put as little work as possible in the pipeline of work so that the team can recover quickly from unplanned work. The ideal scenario is that you are constantly about to run out of work but you never really do. It enables a highly flexible relationship with product management too. The product team can change plans whenever they want as long as the work they prepare is ready to go.