clement13.net
Original photo: Nef d’un atelier d’entretien ferroviaire, avec sa fosse et ses rails, ses étagères et ses rangements alignés.
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
Original photo, unretouched. The background is a version of it stylised by the site.

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.

Guide≈ 19 min readPartly checkedPartial checkThe main facts were checked by searching the cited sources. The items below still need checking before relying on them.To re-check
  • Disponibilité de l'envoi de work item à l'agent Copilot sur Azure DevOps Server on-premise non confirmée (GA annoncée pour Azure Boards/Services).
Written with AI assistance; sources are cited at the bottom of the page. An error? Report it via clement13.net.
Reading
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

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
⚠️ Pitfall

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.

💡 Expert tip

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.

✅ Good practice

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
🧪 Example

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).

⚠️ Pitfall

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
💡 Expert tip

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:

  1. Planning: drag and drop items from the backlog into the sprint; total estimate (points/hours) appears.
  2. 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.
  3. Taskboard: To Do / In Progress / Done columns for tasks; update of Remaining Work; sprint burndown calculated in remaining hours or tasks (depending on settings).
⚠️ Pitfall

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”).

⚠️ Pitfall

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.
✅ Good practice

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.

⚠️ Pitfall

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.

⚠️ Pitfall

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
⚠️ Pitfall

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#

⚠️ Pitfall

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.

⚠️ Pitfall

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.

⚠️ Pitfall

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.

⚠️ Pitfall

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.

💡 Expert tip

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.

🧪 Example

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.

⚠️ Pitfall

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
✅ Good practice

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.

⚠️ Pitfall

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#

  1. A short hierarchy: Epic → Feature → Story → Task. Beyond that, no one can keep track.
  2. Written definitions of ready and done in the project wiki, linked to the backlog.
  3. One field, one decision: no field without a consumer.
  4. Teams by value stream, not by technical layer (avoid “the database team” and “the reporting team” passing tickets back and forth).
  5. Consistent title naming: action verb + object (“Calculate linear shelf space by sector”).
  6. Systematically link tasks ↔ changesets, bugs ↔ stories, stories ↔ features; verify by query (“stories without parent,” “bugs without code link”).
  7. Backlog hygiene: quarterly review; any item with no movement for 6 months is either closed or refined (see metrics — backlog health).
  8. Document the model: a wiki page “How we use the tool” (types, states, fields, links, conventions), reviewed whenever someone new joins.
  9. Separate data incidents from software bugs: dedicated types, dedicated SLAs.
  10. 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#

✻ Written by Claude Sonnet 5.5