

- Description
- Nef d’un atelier d’entretien ferroviaire, avec sa fosse et ses rails, ses étagères et ses rangements alignés.
- Source
- Samuel Zeller samuelzeller · original page
- Licence
- CC0 Public domain
Azure DevOps Server (ex-TFS) in Depth
You will be able to describe the Server → collections → projects → teams organization, and what is shared or isolated at each level.
In brief
- You will be able to describe the Server → collections → projects → teams organization, and what is shared or isolated at each level.
- You will know how to choose and customize a process template (Agile, Scrum, CMMI, Basic, inherited process) without falling into pitfalls.
- You will master work items, states, links, area/iteration paths, backlogs, boards, capacity, WIQL queries, dashboards.
- You will know how to connect Power BI to work items (Analytics/OData), use the REST API, and plan a migration.
- Common thread: a SQL Server datamart fed by an SFA application, multilingual Power BI reports, versioned in TFVC, delivered as installation kits. For version control, see TFVC in Depth.
Rating context: team of 5 to 15 people, on-premise data/BI project; /5 ratings are assessments (see RATING).
On this page
- 🟢 Novice — What is it, and what is it called today
- 🟢 Novice — Organization: collection, project, team
- 🟢 Novice — Process templates and work item types
- 🟡 Hands-on — Links between work items
- 🟡 Practice — Area paths and iteration paths
- 🟡 Practice — Backlogs, boards, sprints, capacity
- 🟡 Practice — WIQL queries
- 🟡 Practice — Dashboards and widgets
- 🔴 Expert — Analytics, OData, and Power BI on work items
- 🔴 Expert — REST API, extensions, and automation
- 🔴 Expert — Inherited process and customization pitfalls
- 🔴 Expert — Test Plans and Pipelines, in two useful words for data projects
- 🔴 Expert — Migration timeline and plan
- 🔴 Expert — Structuring good practices
- Metrics — tool rating
- 🤖 AI contribution
- See also
Level: 🟢→🔴
🟢 Novice — What is it, and what is it called today#
Team Foundation Server (TFS) is the former name of Microsoft's collaboration server (code, tickets, builds, tests). It was renamed Visual Studio Team Services (VSTS) on the cloud side, then Azure DevOps Services, and Azure DevOps Server on the on-premise side (starting with version 2019). The names coexist in people's minds and in paths: people still say “TFS.”
The features are grouped into services:
| Service | Content | General-purpose equivalent |
|---|---|---|
| Boards | work items, backlogs, boards, sprints, queries | Jira |
| Repos | Git repositories and TFVC | GitHub/GitLab (+ legacy TFVC) |
| Pipelines | build (CI) and release (CD), YAML or classic designer | GitHub Actions, GitLab CI |
| Test Plans | manual and exploratory test plans | Xray, Zephyr |
| Artifacts | package feeds (NuGet, npm, Maven, Python, universal) | Artifactory |
| Wiki | versioned Markdown documentation | Confluence |
Symptom: Microsoft documentation “doesn't match” what you see. Cause: some pages describe Azure DevOps Services (cloud), others describe Server. Features arrive in Services first. Fix: at the top of each docs page, choose the “Azure DevOps Server” version selector (or the exact version); when in doubt, verify in the interface.
🟢 A modern lifecycle#
According to Microsoft announcements in late 2025, Azure DevOps Server is no longer year-based: the latest version (announced December 9, 2025) is delivered under the Modern Lifecycle Policy, without a year number or fixed end-of-support date as long as you stay current with updates and system prerequisites (status 2026-10, to be rechecked on the official lifecycle page before any upgrade decision). Practical consequence: you no longer choose “2022 vs 2025,” you commit to following updates, as with a service.
The risk of an unmaintained on-premise TFS is not failure, it's silent obsolescence: operating system, SQL Server, build agents, TLS protocol. Put updates on the team schedule, like an annual maintenance sprint.
🟢 Novice — Organization: collection, project, team#
Azure DevOps Server
└─ Project collection (e.g. DefaultCollection) ← 1 SQL database per collection
├─ Project “MyProduct” (process: Agile/Scrum/CMMI/Basic)
│ ├─ Team “Datamart” (backlog, sprints, capacity, board)
│ ├─ Team “Reports”
│ └─ Team “Support”
└─ Project “Internal tools”
- The server hosts one or more collections. A collection = an administration, backup, and upgrade unit = one SQL database (
Tfs_<Collection>). A collection can be detached/attached (useful for migration, see below). - The project (formerly “team project”) groups work items, repositories, pipelines, wiki. It applies a process template. Area paths and iteration paths form the organizational and planning tree.
- The team is a view: it selects area paths (what it owns) and iteration paths (its sprints), has a backlog, a board, capacity, dashboard widgets. A project can have multiple teams; a user can join several.
How many projects should you create?#
Expert rule: fewer projects, more teams. A project = a hard boundary (permissions, process, limited cross-project queries). One project per application multiplies admin overhead and makes cross-cutting reporting painful. Create a separate project only for: a confidentiality requirement, an incompatible process, or an independent lifecycle.
| Choice | Advantages | Drawbacks |
|---|---|---|
| 1 project, N teams | cross-cutting queries, one process, one shared parent backlog | finer permissions to set, area/iteration trees require discipline |
| N projects | strong isolation | no simple native cross-project parent-child link (links exist, aggregated backlogs do not), N configurations |
🟢 Novice — Process templates and work item types#
The process template determines work item types, their states, and fields.
| Process | Typical hierarchy | States for a content item | Mindset |
|---|---|---|---|
| Agile | Epic → Feature → User Story → Task ; Bug, Issue | New → Active → Resolved → Closed (Removed) | general-purpose agile teams |
| Scrum | Epic → Feature → Product Backlog Item → Task ; Bug, Impediment | New → Approved → Committed → Done (Removed) | faithful Scrum vocabulary |
| CMMI | Epic → Feature → Requirement → Task ; Bug, Change Request, Review, Risk, Issue | Proposed → Active → Resolved → Closed | formal process, requirements traceability, audit |
| Basic | Epic → Issue → Task | To Do → Doing → Done | simple start (available on Services and recent Server versions; check based on installed version) |
Some major types:
- Epic: major initiative (multiple quarters). Feature: deliverable capability (a few sprints). Story / PBI / Requirement: value deliverable in one sprint. Task: technical action (hours). Bug: defect; it can be tracked as a story or as a task depending on team backlog configuration (team-level “bugs” setting). Issue / Impediment: blocker to remove. Test Case / Test Plan / Test Suite: Test Plans service types.
🟢 States, reasons, and rules#
Each type has its states (field System.State) and, for each transition, reasons (System.Reason). Rules (required fields by state, automatic values, read-only fields) accompany each transition. Example for an Agile process Bug: transition to Resolved → “Resolved Reason” field (Fixed, As Designed, Cannot Reproduce...); transition to Closed → verification by tester.
States should reflect the real flow and be few in number (4 to 6). Every additional state is one more column to move, one more statistics field to maintain, one more flow metric to interpret.
🟡 Hands-on — Links between work items#
Links are the tool's real value: they turn a list into a traceable graph.
| Link type | Direction | Usage |
|---|---|---|
| Parent / Child | hierarchy (strictly tree-structured: one parent only) | Epic → Feature → Story → Task ; aggregates progress |
| Related | free association | light dependency, context |
| Predecessor / Successor | order | planning dependency (display in delivery plans) |
| Duplicate / Duplicate Of | duplicate | deduplication |
| Tests / Tested By | test case ↔ story/bug | test coverage |
| Affects / Affected By | impact | relevant to CMMI |
| Changeset / Commit / Pull Request / Build / Found in build / Integrated in build | link to code and CI | traceability ticket → code → delivery |
🟡 Ticket ↔ TFVC changeset link#
In TFVC, check-in associates one or more work items: in Visual Studio (Team Explorer) by checking the item in “Related Work Items”; at the command line with tf checkin /associate:12345,12346 (syntax may vary by tf.exe version, verify with tf checkin /?). The “Work Items” check-in policy can make association mandatory: recommended for any repository that produces delivered kits.
# Check in while associating two tasks and a comment, in a TFVC environment
tf checkin /comment:"Added sector filter in DIM_CLIENT" /associate:12345,12346 /noprompt
# View work items associated with a changeset
tf changeset 45815
A delivered 9.1.4 kit includes 38 changesets, associated with 12 stories. A WIQL query “stories linked to changesets whose date is within the delivery window” automatically produces the release notes: without mandatory links, the team rebuilds these notes manually for every delivery (a few hours, with errors).
Symptom: a dashboard shows “0 linked changeset” even though the team checks in every day. Cause: optional association, never set. Fix: mandatory check-in policy + reminder in code review; batch catch-up is possible from the work item's “Links” tab for past changesets.
🟡 Practice — Area paths and iteration paths#
Area paths: who owns what#
A hierarchical tree (MonProduit\Datamart\Dimensions, MonProduit\Rapports\Rapport Standard…). It is used to: route items to the owning team, restrict access (permissions by area path), filter queries. A team “owns” one or more areas and, optionally, their sub-areas.
Iteration paths: when#
Planning tree (MonProduit\2026\Sprint 26-19). Each node has a start and end date. A team selects the iterations it uses (sprints visible in its backlog). Iterations are shared across the project but enabled per team.
Conventions that avoid trouble#
| Convention | Why |
|---|---|
Name sprints with a sortable format (2026-S19 or Sprint 2026.19) |
alphabetical order = chronological order |
| A single root per theme (by year or by release) | simplify UNDER queries |
| Never rename or delete a used node without reassigning it | the deleted node is replaced by a parent node: the loss of precision is silent |
| “Backlog” iteration (root) for unplanned items | avoids an empty field |
| No more than 3 to 4 area levels | beyond that, governance gets diluted |
For a project that delivers by versions (8.0, 9.1…) and works in sprints, model the version as an area or a field (“Target Version”), not as an iteration: sprints remain time-based, while version is a cross-cutting product property.
🟡 Practice — Backlogs, boards, sprints, capacity#
Azure DevOps provides, per team, several configurable backlog levels:
| Level | Contains | View |
|---|---|---|
| Portfolio (Epics) | initiatives | backlog + board |
| Features | capabilities | backlog + board |
| Product Backlog (Stories/PBI/Requirements) | value items | backlog, Kanban board |
| Sprint Backlog | sprint items + tasks | Taskboard + capacity |
Visible levels are set in Team settings → Backlogs; bugs can be handled as stories, as tasks, or ignored in the backlog.
The Kanban board#
Columns = states, but you can split a column into Doing / Done (“Split columns”); WIP limits per column; swimlanes for expedite items; card rules (color based on a field or tag); Definition of Done criteria (checklist per column). The board respects backlog order (Stack Rank).
Taskboard, capacity, burndown#
The sprint relies on three screens:
- Planning: drag and drop items from the backlog into the sprint; total estimate (points/hours) appears.
- Capacity: per person, days off, activity (Development/Testing/Design…) and capacity per day (hours). Team holidays entered once. Overcommit indicator per person and per activity.
- Taskboard: To Do / In Progress / Done columns for tasks; update of Remaining Work; sprint burndown calculated in remaining hours or tasks (depending on settings).
Symptom: empty or incorrect capacity, meaningless indicators. Cause: activities not filled in on tasks, or missing holidays. Fix: make activity mandatory in the inherited process; configure holidays at the team level; calibrate productive hours per day to 4–6 h.
Tool limits for velocity#
The Velocity widget aggregates points per sprint but does not track historically scope changes during the sprint with the granularity of a dedicated tool; for reliable burnup, use Analytics (see below) or the “Sprint trend” feature. See Project Metrics and Reporting.
🟡 Practice — WIQL queries#
Saved queries are shareable filters (flat list, tree, or direct links). They rely on the WIQL language (Work Item Query Language), close to read-only SQL: SELECT … FROM WorkItems | WorkItemLinks WHERE … ORDER BY ….
-- Active team tasks in the current sprint
SELECT [System.Id], [System.Title], [System.AssignedTo], [Microsoft.VSTS.Scheduling.RemainingWork]
FROM WorkItems
WHERE [System.TeamProject] = @project
AND [System.WorkItemType] = 'Task'
AND [System.State] <> 'Done'
AND [System.IterationPath] = @currentIteration
ORDER BY [System.AssignedTo], [System.Id]
-- Old bugs with no activity for 60 days (backlog health)
SELECT [System.Id], [System.Title], [System.ChangedDate]
FROM WorkItems
WHERE [System.WorkItemType] = 'Bug'
AND [System.State] IN ('New','Active')
AND [System.ChangedDate] < @today - 60
ORDER BY [System.ChangedDate]
-- Stories under a given feature, through hierarchical links
SELECT [System.Id] FROM WorkItemLinks
WHERE [Source].[System.Id] = 1234
AND [System.Links.LinkType] = 'System.LinkTypes.Hierarchy-Forward'
AND [Target].[System.WorkItemType] <> ''
MODE (Recursive)
Useful macros: @Me, @Project, @Today, @CurrentIteration, @TeamAreas, @StartOfWeek. Operators: UNDER (for paths), IN, CONTAINS, WAS EVER (field history), EVER. WAS EVER is valuable for flow data (“items that have been Blocked”).
Symptom: the query “returns 20,000 items” then crashes or truncates. Cause: result limits per query (around 20,000 in the UI; verify by version) and ORDER BY cost on large collections. Fix: bound by area/iteration/date; for large-scale analysis, use Analytics/OData instead of WIQL.
🟡 Practice — Dashboards and widgets#
A team dashboard brings together widgets: Sprint Burndown, Velocity, Cumulative Flow, Cycle Time, Lead Time, Query Results, Chart for Work Items (pie charts, bars by state/assignee), Test Results, Build History, Markdown. Two depths:
- query widgets (a chart based on a saved query): simple, instant, limited to snapshots of the current state;
- Analytics widgets (Velocity, Cycle Time, Lead Time, CFD, Burndown): historical, calculated from the snapshot table.
One dashboard per audience: (1) team (sprint, WIP, blockers), (2) PO (velocity, release burnup, open bugs), (3) leadership (3 to 5 trend indicators). A universal dashboard serves no one.
🔴 Expert — Analytics, OData, and Power BI on work items#
Analytics is the platform's reporting service: a read-only model fed from work items, with history (daily snapshots and revisions). Integrated into Azure DevOps Services; on Azure DevOps Server it is installed and enabled per collection (built in starting with version 2020; on 2019, extension to install — verify based on your version). It uses the search index and a dedicated schema in the collection database.
The three ways to consume it#
| Path | When | Notes |
|---|---|---|
| Analytics Views (configured in the interface) | simple analysis from Power BI Desktop via the “Azure DevOps Server (Boards only)” connector (“Azure DevOps (Boards only)” for Services) | quick to set up, no free-form querying |
OData feed (_odata/v4.0-preview/… or newer version) |
full power: WorkItems, WorkItemSnapshot, WorkItemRevisions, Iterations, Areas, Users, Dates tables… |
server-side URL: https://<serveur>/<collection>/<projet>/_odata/<version>/WorkItems?… |
Aggregated query model $apply |
server-side calculations (aggregations) before import | avoids pulling back millions of rows |
OData example: number of active bugs per iteration (server-side aggregation).
https://<serveur>/<collection>/<projet>/_odata/v4.0-preview/WorkItems?
$apply=filter(WorkItemType eq 'Bug' and State ne 'Closed')/
groupby((Iteration/IterationPath), aggregate($count as Total))
Minimal M (Power Query) example for an OData feed, Windows authentication:
let
Source = OData.Feed(
"https://<serveur>/<collection>/<projet>/_odata/v4.0-preview/WorkItemSnapshot?" &
"$filter=DateValue ge 2026-01-01Z and WorkItemType eq 'User Story'" &
"&$select=WorkItemId,Title,State,StoryPoints,DateValue,AreaSK,IterationSK" &
"&$expand=Iteration($select=IterationPath,StartDate,EndDate)",
null,
[Implementation = "2.0"]
)
in
Source
Recommended data model for a project report#
Tables: WorkItemSnapshot (grain = item × day: flow fact), WorkItem (current dimension), Iteration, Area, User, Date (calendar). Star relationships; flow DAX measures:
Completed items =
CALCULATE ( DISTINCTCOUNT ( WorkItemSnapshot[WorkItemId] ),
WorkItemSnapshot[State] = "Done" )
Average cycle time (days) =
AVERAGEX ( VALUES ( WorkItem[WorkItemId] ), CALCULATE ( MAX ( WorkItem[CycleTimeDays] ) ) )
WIP =
CALCULATE ( DISTINCTCOUNT ( WorkItemSnapshot[WorkItemId] ),
WorkItemSnapshot[State] IN { "Active", "Committed" } )
The CycleTimeDays and LeadTimeDays fields are provided by Analytics. For formulas and interpretation, see 10 — Project Metrics and Reporting; for Power BI model design, see Cross-Cutting Power BI Good Practices.
Symptom: a Power BI report on work items is slow and exceeds quotas. Cause: importing full WorkItemRevisions (millions of rows) without filtering. Fix: filter by date and type, aggregate server-side with $apply, keep only useful columns; use WorkItemSnapshot for trends, WorkItemRevisions only for audit.
Symptom: scheduled refresh fails after moving to an updated server. Cause: gateway identity lacking Analytics read permission, changed certificate, or removed OData version. Fix: dedicated service account with “View analytics” permission, browser test on the OData URL, and documentation of the feed version in use.
When to prefer direct SQL access#
It is tempting to read the collection database (Tfs_<Collection>, tbl_WorkItem* views) in SQL. This is unsupported by Microsoft (internal schema, modified in each version). Use only the Analytics warehouse and documented views, and never write.
🔴 Expert — REST API, extensions, and automation#
REST API#
Root: https://<serveur>/<collection>/<projet>/_apis/…?api-version=<n>. API versions are tied to server version; choose the highest one supported by the target server. Some entry points:
| Need | Entry point |
|---|---|
| Read a work item | GET _apis/wit/workitems/{id}?$expand=relations |
| WIQL query | POST _apis/wit/wiql (body { "query": "…" }) |
| Create / update | POST/PATCH _apis/wit/workitems/${type} (JSON Patch, application/json-patch+json) |
| TFVC changesets | GET _apis/tfvc/changesets/{id}/workItems |
| Team iterations | GET {équipe}/_apis/work/teamsettings/iterations |
| Capacity | GET {équipe}/_apis/work/teamsettings/iterations/{id}/capacities |
# Read a work item (integrated Windows auth, on-premises server)
$uri = "https://tfs.exemple.local/tfs/DefaultCollection/MonProduit/_apis/wit/workitems/12345?`$expand=relations&api-version=7.0"
Invoke-RestMethod -Uri $uri -UseDefaultCredentials -Method Get
Symptom: Invoke-RestMethod -Method Patch returns 415 or an obscure error. Cause: the Content-Type header must be application/json-patch+json, and PowerShell 5.1 sometimes struggles with JSON Patch bodies. Fix: specify -ContentType 'application/json-patch+json' and serialize the body with ConvertTo-Json -Depth 5; as a last resort, use System.Net.Http.HttpClient. (Real-world behavior on 5.1 can be finicky.)
Some reflexes: never write directly to the database; use the API or the official tool; limit throughput (rate limits on Services; on Server, the limit is your infrastructure); paginate with $top and continuationToken.
Extensions#
Extensions add widgets, tabs, menu actions, pipeline tasks, and work item contributions. They are installed per collection (Server version) or per organization (Services). Writing an extension requires: a vss-extension.json manifest, JavaScript/TypeScript or a web page, and packaging with tfx extension create. For a simple need, prefer the REST API from a scheduled script (alerting, synchronization) over an extension.
Rules, hooks, and notifications#
- Process rules (no code): required fields, conditional values.
- Service hooks: trigger a webhook/Teams/Slack on creation or state change.
- Subscription notifications: should be rationalized—too much mail kills the signal.
🔴 Expert — Inherited process and customization pitfalls#
On recent Azure DevOps Server versions, there are two customization models:
| Model | Principle | Usage |
|---|---|---|
| Inherited process (inherited) | you inherit from Agile/Scrum/CMMI/Basic and add fields, states, rules, pages; web interface | recommended: supported, straightforward migrations |
| XML (on-premises XML) | export the template to XML, modify it, reimport it with witadmin |
maximum power, reserved for advanced needs (complex calculated fields, fine-grained transitions); not available on Services |
# Export the “Bug” type from the project (XML)
witadmin exportwitd /collection:https://tfs.exemple.local/tfs/DefaultCollection /p:MonProduit /n:Bug /f:Bug.xml
# Reimport after modification
witadmin importwitd /collection:https://tfs.exemple.local/tfs/DefaultCollection /p:MonProduit /f:Bug.xml
Customization pitfalls#
Field proliferation. Symptom: 40-field forms, nobody fills anything out. Cause: each stakeholder request created a field. Fix: a model governance committee (2 to 3 people), rule: “a field must feed a decision or a report,” annual review and removal of never-populated fields.
Changing a state after the fact. Symptom: incorrect historical reports, broken burndown. Cause: renaming or merging states while thousands of items are in the old state. Fix: add the new state, migrate items by script (API) then remove the old one; recalculate Analytics; notify report consumers.
Divergence between projects. Symptom: three projects, three “Bug” variants; cross-project dashboards no longer work. Cause: process copies modified independently. Fix: one shared parent process used by multiple projects (inherited process); changes in one place.
Free-text fields. Symptom: “Target version” contains 9.1, 9.1.0, V9.1. Cause: text field. Fix: value list (picklist) or identifier field, populated by script for each new version.
Before modifying a process, clone it in a test environment (test collection, or temporary project), apply the change, replay 10 real scenarios, then apply in production during a quiet window. A failed XML customization is slow to undo.
🔴 Expert — Test Plans and Pipelines, in two useful words for data projects#
Test Plans#
A plan contains suites (static, query-based, requirement-based) of test cases (steps, expected results, parameters). Execution produces runs with screenshots, logs, and linked bugs. For a BI project, parameterized test cases are used for number acceptance testing: “for customer X and month M, total report sales = reference value ± tolerance.” The result of each execution is tracked (who, when, which kit version). See Acceptance testing and business validation.
40 parameterized test cases (4 measures × 10 customers) run before each kit. Any variance > 0.5% creates a bug linked to the test case, the story work item, and the kit version. The “test case pass rate by kit” dashboard feeds the release decision.
Pipelines#
YAML pipelines (versioned with code, recommended) or classic pipelines (designer, legacy). For data projects: database project build steps (SSDT/sqlpackage), installation kit build, test script execution, artifact publishing, deployment to an acceptance testing environment. See CI/CD and CI/CD for data: foundations, datamarts, pipelines, and reports.
Symptom: a pre-generation step (documentation scripts) disappears from the repository, and the build breaks (“A path to a .ps1 file is required”). Cause: generated files that are read by the pipeline were excluded from source control. Fix: if the pipeline does not rerun generation, the files it reads must be versioned; verify what each step reads before ignoring a file.
🔴 Expert — Migration timeline and plan#
Three paths, depending on constraints:
| Path | When | Effort | Risks |
|---|---|---|---|
| In-place upgrade / new server (collection restore then version upgrade) | stay on-premises | low to medium | SQL Server/OS prerequisites, build agents, incompatible extensions |
| To Azure DevOps Services (data migration tool, database import) | infrastructure retirement | medium to high | freeze windows, identities (Entra ID), extensions, feature differences |
| To another tool (Jira, GitHub/GitLab…) | enterprise strategy | high | loss of link history, TFVC → Git to be planned separately |
Typical on-premises version upgrade plan (to adapt)#
| Week | Action |
|---|---|
| W−6 | Inventory: server version, SQL, OS, extensions, agents, custom XML processes |
| W−5 | Read release notes and target prerequisites; verify agent and extension compatibility |
| W−4 | Full backup (databases + encryption key); restore to test server |
| W−3 | Upgrade on test server; rerun critical pipelines, queries, and widgets |
| W−2 | Team communication; freeze window (off-hours) |
| W0 | Production upgrade; verification: permissions, builds, queries, Power BI/Analytics reports |
| W+1 | Post-operation review, agent updates, retrospective |
Always test backup restoration. A backup that has never been restored is just a hypothesis. Also back up the database encryption key, without which encrypted collection data cannot be read.
TFVC (legacy) is no longer Microsoft’s recommended path for new projects: the Git repository is the strategic target. Keeping TFVC is possible (the feature remains available in Azure DevOps Server, status 2026-10), but plan the TFVC → Git migration as a separate effort (history to keep or drop, branches to convert, build tooling to adapt). See Git vs TFVC: compare, migrate, coexist and Branching Strategies.
🔴 Expert — Structuring good practices#
- A short hierarchy: Epic → Feature → Story → Task. Beyond that, no one can keep track.
- Written definitions of ready and done in the project wiki, linked to the backlog.
- One field, one decision: no field without a consumer.
- Teams by value stream, not by technical layer (avoid “the database team” and “the reporting team” passing tickets back and forth).
- Consistent title naming: action verb + object (“Calculate linear shelf space by sector”).
- Systematically link tasks ↔ changesets, bugs ↔ stories, stories ↔ features; verify by query (“stories without parent,” “bugs without code link”).
- Backlog hygiene: quarterly review; any item with no movement for 6 months is either closed or refined (see metrics — backlog health).
- Document the model: a wiki page “How we use the tool” (types, states, fields, links, conventions), reviewed whenever someone new joins.
- Separate data incidents from software bugs: dedicated types, dedicated SLAs.
- Measure flow (lead time, cycle time) rather than counting logged hours.
Metrics — tool rating#
| Criterion | Score | Justification (team 5–15, on-prem data/BI) |
|---|---|---|
| Model flexibility | 4/5 | legacy and XML processes cover almost everything; limits on hierarchies with more than three custom levels |
| Reporting | 4/5 | solid Analytics + OData + Power BI; native widgets more limited than dedicated tools |
| Code/CI integration | 5/5 | native TFVC/Git, builds, tests, releases: ticket → changeset traceability |
| Cost | 4/5 | often covered by Visual Studio subscriptions; on-prem administration required |
| Adoption | 3/5 | dated UX, less known to business teams |
| Governance | 4/5 | fine-grained permissions by area/iteration, audit |
| Scalability | 4/5 | multiple collections; decent portfolio view but no native SAFe |
| Process customization | 4/5 | well-controlled inheritance; powerful but risky XML |
| Extensibility / API | 4/5 | full REST, extensions, hooks; thinner marketplace than Jira |
See the comparison in 12 — Comparison.
🤖 AI contribution#
| Use case | Gain /5 | Risk /5 | Maturity /5 | Prerequisites | Safeguards |
|---|---|---|---|---|---|
| Draft acceptance criteria from a story | 4 | 3 | 4 | clear story, business context | PO review; do not invent business rules |
| Generate WIQL/OData queries from French | 3 | 2 | 3 | known field schema | run on a sample, verify counts |
| Summarize a work item history | 4 | 2 | 4 | usable comments | non-contractual summary |
| Send a work item to a coding agent (Copilot) | 3 | 4 | 2 | connected GitHub repositories; Azure Boards feature (Services), general availability announced in December 2025 after a 2025 preview; to be verified for an on-premises installation | mandatory human code review, no sensitive data |
| Detect duplicates | 3 | 2 | 3 | clean history | human confirmation |
Useful prompt: “Here is a story and the domain rules. Propose 5 quantified, testable acceptance criteria. State the assumptions you make.” Details in 11 — AI and tools.
See also#
- Project Planning and Tracking Tools: Overview · Jira In Depth and Alternatives · Project Metrics and Reporting · Comparison of Planning Tools
- TFVC In Depth · Git In Depth · Source Control for Data: SQL and Power BI
- Scrum in Practice · Planning and Estimation (matrix) · Glossary
✻ Written by Claude Sonnet 5.5