User story burndown chart shows incorrect velocity calculation after sprint rollover

Our team dashboard is displaying inconsistent velocity calculations in the burndown widget after we rolled over to Sprint 47. The chart shows 89 story points completed, but our actual closed items total 73 points.

I’ve verified the work item state transitions are correct (New → Active → Closed), and all items are properly assigned to Sprint 47. The KQL query backing the widget seems to be counting items that were moved from Sprint 46, even though they weren’t completed in that sprint.


let sprintPath = "Project\\Team\\Sprint 47";
WorkItems
| where WorkItemType == "User Story"
| where Iteration == sprintPath
| summarize Completed = sumif(StoryPoints, State == "Closed")

The date filtering might be pulling items across sprint boundaries. Has anyone dealt with similar dashboard widget configuration issues where sprint boundary date filtering causes velocity miscalculations?

Also watch out for work item state transition tracking if you have custom workflow states. We added an “In Review” state that wasn’t properly mapped in our burndown calculations, causing similar discrepancies. The dashboard widget configuration needs to know which states count as “completed” for velocity purposes.

The KQL query needs date boundary filtering. Your current query only checks current iteration assignment, not when items were actually completed within sprint timeframes.

We had this problem last quarter. The root cause was items that were closed in Sprint 46 but then moved to Sprint 47 for administrative reasons. They were being double-counted because the query looks at current iteration assignment. You need to filter on StateChangeDate to ensure you’re only counting items that transitioned to Closed during the actual sprint timeframe.

I’ve seen this exact behavior when work items are moved between sprints. The issue is your query doesn’t account for when items were actually closed versus when they were assigned to the sprint. You need to add a time-based filter that checks the ClosedDate against the sprint iteration dates, not just the current Iteration path assignment.

Your issue stems from missing temporal filtering in the KQL query. Let me address each aspect systematically:

KQL Query Optimization: The current query lacks StateChangeDate filtering, which is critical for accurate velocity. You need to correlate when items transitioned to Closed with the sprint’s actual date range.

Sprint Boundary Date Filtering: Retrieve your sprint’s StartDate and EndDate from the Iterations table and use them as hard boundaries:


let sprintStart = datetime(2025-09-01);
let sprintEnd = datetime(2025-09-14);
WorkItems
| where StateChangeDate >= sprintStart and StateChangeDate <= sprintEnd
| where State == "Closed" and WorkItemType == "User Story"
| summarize TotalPoints = sum(StoryPoints)

Work Item State Transition Tracking: Enable historical tracking in your Analytics view (Project Settings → Analytics → Enable historical data). This ensures StateChangeDate captures the exact moment items reached Closed state, not just current assignment.

Dashboard Widget Configuration: In your burndown widget settings:

  1. Set “Time period” to match sprint dates exactly
  2. Under “Advanced options”, enable “Use state change date” instead of “Use iteration path”
  3. Add a filter: `StateChangeDate >= @StartOfIteration AND StateChangeDate <= @EndOfIteration
  4. Verify “Completed” states include only Closed (exclude Removed or Cut states)

The 16-point discrepancy (89 vs 73) likely comes from items closed in Sprint 46 but moved to Sprint 47 afterward. The corrected query ensures you’re counting based on when work was actually completed, not current iteration assignment. This gives you accurate velocity for sprint planning.

Test the updated query in Analytics hub before deploying to your dashboard to verify the 73-point count matches your actual completed work.