Every system has a bottleneck that limits the possible output of that system. Some software teams are organised linearly (work is passed along a chain of teams); in which case the bottleneck is one of those teams. Many software teams are self-organising (or at least seek to be), in this case there will be a person or function in this team which is the bottleneck.
-
Ensure there is a steady supply of work for the bottleneck
As the bottleneck controls our output, and time lost from the bottleneck is lost for the team, we ensure there is always work for the bottleneck to do.
-
Offload the bottleneck from unnecessary tasks
Any work that can be done by others is disbursed to them, freeing the bottleneck up to only do work they must do.
-
Plan others’ work around the bottleneck
The bottleneck’s work (including others work that requires the bottleneck) is planned first. Once it is planned, others work which does not interact with the bottleneck’s can be planned.
-
Ensure quality inputs into the bottleneck
To minimise the risk of bottleneck rework, extra quality steps are introduced immediately before the bottleneck.
Software development is often highly variable in type and length. This makes planning and delivering work reliably difficult. Some variability is intrinsic to the type of work, for this we must ensure the teams are protected from normal variation such they can deliver consistently and at high quality.
-
Ensure the bottleneck’s work is buffered
Adding in a time buffer gives the team a shock absorber to their iterations, allowing for deviations from estimates without compromising agreed deliverables or quality.
-
Make the passing of time visible
The passage of time is visible against the state of completed work, shown as a percentage of the buffer that has been consumed. All team members can clearly see how likely the team is to complete the iteration on time at the current rate.
-
Use an alternate response system
There are set of actions that are reliable at ensuring iterations are delivered on time (without compromising quality) in each team. These are decided by the team and must be executed once the team hits a pre-determined risk point of buffer consumption.
-
Buffer Logging
Hits on the risk point of the buffer and their causes are logged. This list is used to address the frequent or systematic causes of variation within the team as a process of ongoing improvement.
External variation has a high impact on the speed at which teams can complete iterations. To further accelerate the performance of the team we must limit the amount of work exposed to the impacts of external variation, as well as the team behaviours caused by due dates. The outcome is starting and completing iterations quickly and consistently.
-
Smaller chunks of work
The shorter the iteration, the less likely it is to be impacted by external variation before it is completed. Iteration based steps such as reviews also occur on smaller sections of work, more frequently, increasing quality. Iterations are planned to their true estimated length, not forced into a pre-planned timebox length.
-
Use time buffers not deadlines
As tasks are completed, new tasks flow to the team to be started. Tasks are managed on buffer consumption as their risk measure. There is no batching of iterations into time-boxes with due dates.
-
Limit work in progress
To reduce the time taken to complete an iteration we limit the window of tasks available to the team. This limits multitasking and reduces handover times. This allows us to have a well-balanced team where the most relevant task is available but resources are not overloaded.
-
Have a relevant mix of tasks
The mix of task types for the team is decided strategically. The next task to flow to the team to be started is the same type as the one completed. This provides predictable completion of work (for example features, bug fixes, customisations).