Project Management & Agile Module 9 – Kanban and flow
Flow metrics: WIP, throughput, age, cycle time
Compute the four flow metrics a Kanban system must track from one board export of 170 work items, and read the cycle-time scatterplot they draw.
What you will learn
- Compute WIP, throughput, work item age and cycle time from a board export
- Read a cycle-time scatterplot and a cumulative flow diagram
- Set a service level expectation from past cycle times and age the open work against it
- Apply Little's law to a window of flow data and test whether it was stable
Before you start
What you’ll learn · Before you start
What you will learn
- Compute WIP, throughput, work item age and cycle time from a board export
- Read a cycle-time scatterplot and a cumulative flow diagram
- Set a service level expectation from past cycle times and age the open work against it
- Apply Little's law to a window of flow data and test whether it was stable
Before you start
On this page
The IT helpdesk of a college finished 140 requests in a 90-day stretch, about 11 a week, and the middle request took 3 days. Both numbers look healthy, yet on the last day 30 requests were still open and the oldest had been in progress for 41 days. Counting hours would have hidden that; counting work items shows it.
Kanban requires four measurements at a minimum: WIP, throughput, work item age and cycle time. You will compute all four from one board export of 170 items, read the chart the cycle times draw, and see which question each measurement answers and which it cannot. Every figure comes from that export.
The four counts a Kanban board must give you
The export has five columns: an id, a work item type, and the days the item was created, started and finished, with an empty cell where either has not happened. All four mandatory flow metrics: The minimum set of measurements a Kanban system collects: work in progress, throughput, work item age and cycle time, each taken between the started and finished points the team has defined. are measured between the started and finished points of the team’s Definition of Workflow.
work in progress (WIP): The number of work items that have been started but not finished. One of the four flow metrics the Kanban Guide requires. More in “Lean flow: waste, Little's law and constraints” is the number of items started but not finished, counted at a moment rather than over a period. Here it was 6 at the end of week 7, 43 at the end of week 10 and 30 on day 90.
throughput: The number of work items finished per unit of time, counted as whole items rather than estimated in points or hours. More in “Lean flow: waste, Little's law and constraints” is the number of items finished per unit of time: “the exact count of work items” (Kanban Guide), never an estimate in points or hours. This helpdesk finished 140 items in 90 days, 10.9 a week, with weekly counts from 5 to 17.
An estimate reported as throughput
Wrong: “the team delivered 46 points this week.” Right: “the team finished 17 items this week.” Anyone can recount items on the board; a total of estimates cannot be checked at all.
work item age: The elapsed time between the moment a work item started and today, so only items that have not finished yet have one. is how long an item has been in progress so far, so only unfinished items have one. It is the one measurement about work in front of the team: 30 items were open on day 90, the oldest for 41 days.
cycle time: The elapsed time between the moment a work item starts and the moment it finishes, as the team has defined those two points. More in “Lean flow: waste, Little's law and constraints” is the elapsed time from an item’s start to its finish, so only finished items have one. Over the 90 days the median was 3 days, the longest took 32, and 85 % came in at or under 15 days. One program computes all four, week by week:
"""The four mandatory flow metrics of one Kanban board, from its export.
Reads board-export.csv beside this file: 170 work items of a college IT helpdesk
over 90 days, with the columns id, type, created, started and finished. An empty
started or finished column means the item has not started or has not finished.
Day 1 is the first day of the export, so every figure below is a day number and
nothing depends on a calendar. Cycle time and work item age count whole days
inclusive, so an item started and finished on one day took one day.
The service level expectation at the end comes from the first seven weeks alone,
the stretch before an end-of-term rush changed the system.
"""
import csv
import datetime as dt
import statistics
DAYS = 90
WEEKS = 12
def load(path: str = "board-export.csv") -> list[dict]:
with open(path, newline="", encoding="utf-8") as handle:
rows = list(csv.DictReader(handle))
first = min(dt.date.fromisoformat(row["created"]) for row in rows)
def day(value: str) -> int | None:
if not value:
return None
return (dt.date.fromisoformat(value) - first).days + 1
return [
{
"id": row["id"],
"type": row["type"],
"created": day(row["created"]),
"started": day(row["started"]),
"finished": day(row["finished"]),
}
for row in rows
]
def wip_on(items: list[dict], day: int) -> int:
"""Items started on or before this day and not finished by the end of it."""
return sum(
1
for item in items
if item["started"] is not None
and item["started"] <= day
and (item["finished"] is None or item["finished"] > day)
)
def finished_in(items: list[dict], first: int, last: int) -> list[dict]:
return [i for i in items if i["finished"] is not None and first <= i["finished"] <= last]
def percentile(values: list[int], pct: int) -> int:
"""Nearest rank: the smallest value with at least pct % of the items at or below it."""
ordered = sorted(values)
rank = -(-len(ordered) * pct // 100)
return ordered[rank - 1]
def cycle_times(items: list[dict]) -> list[int]:
return [i["finished"] - i["started"] + 1 for i in items]
def median(values: list[int]) -> str:
"""The median as it reads: 11.5 stays 11.5, 3.0 prints as 3."""
return f"{statistics.median(values):g}"
board = load()
done = finished_in(board, 1, DAYS)
openwork = [i for i in board if i["started"] is not None and i["finished"] is None]
print(f"{len(board)} items arrived, {len(done)} finished, {len(openwork)} still open on day {DAYS}")
for day in (49, 70, DAYS):
print(f"WIP on day {day:2d}: {wip_on(board, day):2d} items started and not finished")
print("\nweek arrived finished WIP at week end")
for week in range(WEEKS):
first, last = week * 7 + 1, week * 7 + 7
arrived = sum(1 for i in board if first <= i["created"] <= last)
print(f"{week + 1:4d} {arrived:7d} {len(finished_in(board, first, last)):8d} {wip_on(board, last):15d}")
print(f"throughput: {len(done)} items in {DAYS} days = {len(done) / (DAYS / 7):.1f} a week")
ages = sorted(DAYS - i["started"] + 1 for i in openwork)
print(f"\nwork item age of the {len(ages)} open items: median {median(ages)}, oldest {ages[-1]} days")
whole = cycle_times(done)
print(
f"cycle time of the {len(whole)} finished items: median {median(whole)},"
f" 85th {percentile(whole, 85)}, 95th {percentile(whole, 95)}, longest {max(whole)} days"
)
stable = cycle_times(finished_in(board, 1, 49))
print(
f"first seven weeks only ({len(stable)} finished): median {median(stable)},"
f" 85th {percentile(stable, 85)}, 95th {percentile(stable, 95)} days"
)
print(f"SLE from those weeks: 85% of work items finish in {percentile(stable, 85)} days or less") Output
170 items arrived, 140 finished, 30 still open on day 90 WIP on day 49: 6 items started and not finished WIP on day 70: 43 items started and not finished WIP on day 90: 30 items started and not finished week arrived finished WIP at week end 1 12 10 2 2 9 5 6 3 7 12 1 4 12 11 2 5 11 8 5 6 10 12 3 7 14 11 6 8 22 10 18 9 24 13 29 10 23 9 43 11 8 17 34 12 8 14 28 throughput: 140 items in 90 days = 10.9 a week work item age of the 30 open items: median 11.5, oldest 41 days cycle time of the 140 finished items: median 3, 85th 15, 95th 27, longest 32 days first seven weeks only (69 finished): median 2, 85th 5, 95th 8 days SLE from those weeks: 85% of work items finish in 5 days or less
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 metrics.py
The week table is where they meet: weeks 1 to 7 keep 1 to 6 items open, while weeks 8 to 10 bring 22, 24 and 23 arrivals against finishes near 10, so WIP climbs to 43.
Key idea
The four counts answer four questions: how much work is open, how fast it leaves, how long the open work has waited, and how long finished work took.
Checkpoint
Check: WIP, throughput, work item age and cycle time
Every finished item on one chart, and the spread it shows
A median describes one item in the middle; a cycle-time scatterplot: A chart with one dot for every finished work item, placed at the day it finished and the number of days it took, so the whole spread of cycle times and its outliers are visible. shows all of them, one dot per finished item at the day it finished and the days it took:
Cycle time of every finished item, against the day it finished
Text description of the diagram
The horizontal axis is the day the item finished, from 0 to 90; the vertical axis is its cycle time in days, from 0 to 32, with grid lines every 8 days. Each of the 140 finished work items is one dot.
- Up to the dotted vertical line at day 49, the end of week 7, the dots sit in a band close to the horizontal axis: 67 of those 69 items took 8 days or less, and the slowest took 9. - After day 49 the dots spread upwards: items finishing in weeks 8 to 12 reach 10, 20 and 30 days, and the highest dot is the longest cycle time of the board, 32 days, finished on day 78. - The dashed horizontal line at 15 days is the 85th percentile of all 140 cycle times: 120 of the dots are on or below it and 20 are above it. - The dots stay dense near the bottom throughout, because the median cycle time over the whole stretch is 3 days.
The shape of the cloud is the point: the same team, the same workflow, and a spread that grew from a few days to more than four weeks once the number of items in progress grew.
Up to the dotted line at day 49 the dots stay in a band of 1 to 9 days; after it they climb, and all 20 items above the dashed 85th-percentile line at 15 days finished in weeks 8 to 12. A median hides that change.
A promise, two charts and a law take these counts further, each worked below. A service level expectation turns one percentile of past cycle times into a promise, such as 85 % of items inside a stated number of days. aging WIP: A view that sets the age of every unfinished work item beside the service level expectation, so slow work can be acted on while it is still open. sets each unfinished item’s age beside that expectation, so slow work is acted on before it is late. A cumulative flow diagram: A chart that stacks the counts of work items in each state over time, so that a band which widens shows a growing queue in that state. stacks the item counts of each state over time, and a widening band is a growing queue. Little's law: For a stable queue, the average number of items in the system equals the arrival rate times the average time an item spends in it: in flow words, work in progress equals throughput times cycle time. More in “Lean flow: waste, Little's law and constraints” relates the averages: average WIP divided by average throughput is the average time an item spends in the system.
The export is an ordinary CSV: MySmartCoPilot’s CSV editor sorts and filters its rows, and the line graph maker plots the program’s week table as two lines, WIP and finishes.
Checkpoint
Check: The spread of cycle times on a scatterplot
Setting a service level expectation, and aging the open work Pro: opens with a Pro, Premium or Ultimate pass
A service level expectation is the only delivery promise a team can make from its own history without guessing. This part takes one from the first seven weeks of this board, measures every open item against it, and sets out what to do at each age.
In this part:
- Why an average cycle time makes a promise you cannot keep
- The five-day expectation this board supports, and the week it broke
- What the team does at each age bucket
1 runnable example (Python) · about 7 minutes
Opening this part with your pass…
This part opens with any MySmartCoPilot pass.
- Pro pass · 1 week₹79$2.99
- 30 days₹179$5.99
- 1 year₹1,699$45
One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.
Passes can’t be bought right now, so this part can’t be opened at the moment. The free part above stands on its own. If you have a pass, enter your licence key.
It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).
Reading a cumulative flow diagram, and using Little's law honestly Pro: opens with a Pro, Premium or Ultimate pass
A cumulative flow diagram puts all 90 days in one picture: stacked bands whose thickness is WIP and whose slopes are the rates at which work starts and finishes. Little’s law then connects the averages, and this board shows what happens when the condition behind the law does not hold.
In this part:
- What the two bands of a cumulative flow diagram say
- The law that ties the three averages, and when it holds
1 diagram · 1 runnable example (Python) · about 7 minutes
Opening this part with your pass…Pro part. It opens with the same pass as the part above.
Practise: the four counts on this board
Every answer below can be checked against the table the program printed:
Practice that adapts to you
Practise this lesson
5 questions about 6 ideas of this lesson. Each answer is explained at once, and what you get right is kept in this browser.
Interview questions
Warm-up: how do work item age and cycle time differ, and what is each one for?
Both measure elapsed time from the moment an item started, but they look in opposite directions. Cycle time belongs to finished items and describes the past: the 140 finished requests had a median of 3 days and an 85th percentile of 15. Work item age belongs to open items and describes the present: 30 were open on day 90, the oldest for 41 days. Age is the number a team can still act on today.
Three harder questions follow: a promise asked of a team with no history, a widening band, and a forecast from a growing queue.
-
Mid to senior
Your support team is asked to publish a delivery promise. The board holds twelve weeks of history: the first five were quiet, the last seven ran through a migration with twice as much work open. What do you publish, and how do you work it out?
-
Mid to staff
A colleague sends you the cumulative flow diagram of their quarter. The finished band climbs at a steady slope, the band above it widens from 4 items to 26 over six weeks, and the team insists throughput has not changed. What is happening, and what do you ask them for?
-
Senior to staff
A delivery lead carries 48 items in progress, finishes 6 a week, and tells a customer their new request will take eight weeks because 48 divided by 6 is 8. The queue has grown every week for two months. What is wrong with the forecast, and what would you say instead?
Flashcards · 4 cards
Recall it, then check
Say the answer to yourself before you look: recalling it is what makes it stick.
-
What are the four flow metrics a Kanban system must collect?
WIP (items started but not finished, counted at a moment), throughput (items finished per unit of time — exact count, not estimates), work item age (how long an open item has been in progress) and cycle time (elapsed time from start to finish, finished items only).
-
How do work item age and cycle time differ, and why does age matter?
Both measure elapsed time from the start of an item. Cycle time belongs to finished items and describes the past (median 3 days, 85th percentile 15 here). Age belongs to open items and describes the present — the oldest open ticket here was 41 days. Age is the number a team can still act on today.
-
Why is throughput an exact item count, not a total of estimates?
The Kanban Guide calls throughput "the exact count of work items" per period. Anyone can recount items on the board, while a total of points or hours cannot be checked at all, so say "the team finished 17 items this week", not "the team delivered 46 points".
-
What does a cycle-time scatterplot show that a median hides?
Every finished item as a dot at the day it finished and the days it took, so the whole spread is visible. Here, dots stayed in a band of 1-9 days for seven weeks and climbed afterwards; the median of 3 days hid 20 items that took more than 15.
Key takeaways
- WIP, throughput, work item age and cycle time are the four measurements a Kanban system must collect, counted in whole items between the team’s own started and finished points.
- WIP is counted at a moment and throughput over a period, so 43 items open and 10.9 finished a week answer different questions.
- Work item age is the only one of the four about unfinished work, which is why the oldest open request here, at 41 days, appears in no cycle-time report.
- A scatterplot shows the whole spread: a median of 3 days and 20 items above 15 days.
Terms in this lesson
- aging WIP
- A view that sets the age of every unfinished work item beside the service level expectation, so slow work can be acted on while it is still open.
- cumulative flow diagram
- A chart that stacks the counts of work items in each state over time, so that a band which widens shows a growing queue in that state.
- cycle-time scatterplot
- A chart with one dot for every finished work item, placed at the day it finished and the number of days it took, so the whole spread of cycle times and its outliers are visible.
- flow metrics
- The minimum set of measurements a Kanban system collects: work in progress, throughput, work item age and cycle time, each taken between the started and finished points the team has defined.
- work item age
- The elapsed time between the moment a work item started and today, so only items that have not finished yet have one.
References
- The Kanban Guide, version 2025.5 (Orderly Disruption Limited and Daniel S. Vacanti, Inc.)
- A Proof for the Queuing Formula: L = λW, Operations Research 9(3), 383-387 (Institute for Operations Research and the Management Sciences (INFORMS))
- statistics: mathematical statistics functions (Python 3.14 standard library) (Python Software Foundation)
- csv: CSV file reading and writing (Python 3.14 standard library) (Python Software Foundation)
Related tools
Report a problem with this lesson
Kept only in this browser. Your Learn progress