What is velocity, and how do you measure it in Metabase?
Velocity is the number of story points (or items) a team completes per sprint. It is the most used and most misused metric in agile delivery: genuinely useful for planning the next sprint and projecting a release burndown, and reliably corrupted the moment it becomes a target. Measure it in Metabase from sprint and issue data synced from Jira, Linear, or Azure DevOps.
TL;DR — completed points per sprint, planned against a rolling 3-sprint average. It's a capacity signal for the team's own planning, not a productivity KPI: points aren't standardized across teams, so comparisons and targets don't measure anything except how fast estimates inflate.
What does velocity measure?
The team's demonstrated capacity, in its own units. Points encode a team's private calibration of effort and uncertainty, which makes velocity good at exactly one job — answering "how much should we commit next sprint?" — and bad at every job it gets drafted into:
Planning signal — the rolling 3-sprint average is the commitment baseline, and remaining scope divided by it is the finish-line projection on the release burndown. This is the legitimate use.
Not a cross-team comparison — points aren't standardized, so a leaderboard of velocities compares units, not output. Teams asked to compete on it simply re-price their points.
Not a target — Goodhart's law applies with unusual force because the team both produces the number and defines its unit. "Increase velocity 20%" is satisfiable by estimating 20% higher, and eventually — under enough pressure — that's what happens, silently, and the planning value is gone.
For questions about whether delivery is actually getting better, use metrics with fixed units: cycle time and lead time measured in days, or task throughput in items. Velocity's companion number is the say-do ratio — committed points versus completed points — which catches chronic over-commitment without turning points into a performance score.
What data does it need?
A sprints table (id, name, started_at, ended_at) and an issues table with sprint_id, story_points, status_category, and completed_at.
A consistent completion rule: points count in the sprint where the issue finished, and carryover counts once, at completion.
For say-do ratio: sprint membership at sprint start — from Jira's sprint scope history or a snapshot taken when the sprint opens. Current-state data can't distinguish committed work from mid-sprint additions, so without that history, report velocity alone and skip the ratio.
SQL patterns
Completed points per sprint with rolling 3-sprint averagePostgreSQL
SELECT
s.name AS sprint,
s.ended_at::date AS sprint_end,
SUM(i.story_points) AS completed_points,
ROUND(AVG(SUM(i.story_points)) OVER (
ORDER BY s.ended_at
ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
), 1) AS rolling_3_sprint_avg
FROM sprints s
JOIN issues i ON i.sprint_id = s.id
WHERE i.status_category = 'done'
AND i.completed_at <= s.ended_at
GROUP BY s.id, s.name, s.ended_at
ORDER BY s.ended_at;
Committed vs. completed (say-do ratio) per sprintPostgreSQL
SELECT
s.name AS sprint,
SUM(si.story_points) FILTER (WHERE si.in_sprint_at_start)
AS committed_points,
SUM(si.story_points) FILTER (
WHERE si.in_sprint_at_start AND si.completed_in_sprint
) AS completed_committed_points,
ROUND(
100.0 * SUM(si.story_points) FILTER (
WHERE si.in_sprint_at_start AND si.completed_in_sprint
) / NULLIF(
SUM(si.story_points) FILTER (WHERE si.in_sprint_at_start), 0
), 1
) AS say_do_ratio_pct
FROM sprint_issues si
JOIN sprints s ON s.id = si.sprint_id
GROUP BY s.id, s.name
ORDER BY MAX(s.ended_at) DESC
LIMIT 12;
Pitfalls
Setting velocity targets.→ The team defines the unit and produces the number, so a target is an instruction to inflate estimates. Velocity drifts up, capacity doesn't, and the forecast the metric existed for stops working.
Cross-team velocity comparisons.→ Points are team-local by construction. Ranking teams by velocity compares calibrations, not output — and teaches every team to re-price its points for the leaderboard.
Planning on last sprint's number.→ Single-sprint velocity swings with holidays, incidents, and one story slipping a day. Commit against the rolling 3-sprint average and treat individual sprints as data points, not baselines.
Double-counting carryover.→ An issue that spans sprints must contribute its points exactly once — at completion. Crediting both sprints, or re-crediting re-estimated leftovers, inflates velocity in a way nobody notices until the release forecast misses.
Where this metric applies
Jira + Metabase — sprint points with scope history for say-do
No, and treating it as one breaks it. Velocity is a capacity signal: how many points this team, with its estimation habits, completes per sprint — useful for forecasting the next sprint and projecting a release burndown, nothing more. The moment management targets it, Goodhart's law kicks in: estimates inflate, and the number rises while nothing real changes. Teams that want an outcome measure should look at flow — cycle time, throughput, lead time — not at points.
Can I compare velocity across teams?
No. A story point is a team-local unit — one team's 3 is another team's 8, because points encode each team's own calibration of effort and uncertainty. Summing or ranking velocities across teams compares measurements taken in different units, and the usual result is that every team re-calibrates its estimates to look good in the ranking, destroying the metric's planning value in the process. Compare a team against its own history; for cross-team questions, use throughput of comparable item types or flow metrics measured in time.
Why a rolling 3-sprint average?
Single-sprint velocity is noisy — holidays, on-call rotations, one oversized story slipping by a day — and planning against the noise means alternating over- and under-commitment. A rolling 3-sprint average smooths the variance while still tracking real capacity changes within a quarter. Use the rolling number for sprint commitments and for the finish-line projection on the release burndown; look at single sprints only to investigate why one deviated.
How should carryover work count?
Count points in the sprint where the work finished, not where it started — an issue that spans two sprints contributes its full points once, at completion. The important discipline is consistency, because double-counting carryover (crediting it to both sprints) or re-crediting re-estimated leftovers quietly inflates velocity. Chronic carryover is worth tracking on its own as a falling say-do ratio: committed points that keep sliding to the next sprint signal over-commitment or oversized stories, both fixable.
How do you track velocity in Metabase?
Sync sprint and issue data from Jira, Linear, or Azure DevOps into a database via an ETL tool, and model completed points per sprint with a window-function rolling average. For say-do ratio you also need sprint membership at sprint start — Jira's sprint scope history or a snapshot taken when the sprint opens — since current-state data can't tell committed work from mid-sprint additions. Pin both to a velocity dashboard next to the sprint health dashboard.