Quick Answer
The Azure DevOps Data Migration Tool (OpsImport) performs a high-fidelity migration of project collections from Azure DevOps Server to Azure DevOps Services, preserving full history of source code, work items, builds, and identities. The process involves running the migration tool to validate and generate import files, uploading the DACPAC database export to Azure blob storage, submitting the import request, and completing identity mapping to link on-premises Active Directory accounts to Azure AD identities.
Detailed Answer
Think of migrating from Azure DevOps Server to Services like moving an entire museum collection from one building to another across the country. You cannot simply load paintings into a truck: each piece must be cataloged, wrapped in appropriate protective materials, transported in climate-controlled vehicles, and reinstalled in the new building with the same spatial relationships, labels, and security settings. The catalog (identities) must be translated because room numbers (Active Directory SIDs) are different in the new building (Azure AD). The Data Migration Tool is the professional moving company that handles all of this complexity: it exports the database, ships it to Azure, imports it, and maps the old identity references to new ones. The migration begins with preparation and validation. You must be running a supported version of Azure DevOps Server (2019 or later, with latest updates). The Data Migration Tool validates your collection against a set of readiness checks: unsupported field types, oversized attachments, deprecated features in use, identity conflicts, and data integrity issues. Common blocking issues include Git repositories exceeding 10GB, TFVC files exceeding 1GB, custom process templates with unsupported elements, and work items with more than 1000 revisions. The validation report identifies these issues and provides remediation guidance. Some issues require modifying data before migration; others simply generate warnings about features that will behave differently in Services. The actual migration process has two modes: dry run (import with no data, just validation) and production import. For the production import, you generate a DACPAC (Data-Tier Application Package) from your collection database using SQL Server tools. This DACPAC is a compressed export of the entire database schema and data. You upload the DACPAC to an Azure blob storage container provided by Microsoft during the import setup. For large databases, this upload can take hours or days depending on bandwidth. Microsoft then processes the import on their infrastructure, applying schema transformations to adapt the on-premises database structure to the multi-tenant Services format. The import duration depends on database size: small collections (under 10GB) complete in hours, while large collections (500GB+) may take days. Identity mapping is the most complex aspect of the migration. On-premises Azure DevOps Server uses Active Directory (AD) security identifiers (SIDs) for all permissions, work item assignments, and history attribution. Azure DevOps Services uses Azure Active Directory (Azure AD) identities. The migration tool generates an identity map file listing every AD identity referenced in the collection and requiring you to map each to a corresponding Azure AD identity. For organizations that have already synchronized their AD to Azure AD using Azure AD Connect, many mappings are automatic. For identities that have no Azure AD equivalent (departed employees, service accounts, renamed accounts), you must decide whether to map them to existing Azure AD accounts or leave them as historical references. Incorrect identity mapping results in permission errors and misattributed history. Post-migration validation and cutover planning are critical. During migration, the source Server is taken offline (or set to read-only) to prevent changes that would not be captured in the migration. After import completes, you validate that all repositories, work items, pipelines, and permissions exist correctly in Services. Pipelines need reconfiguration because Service Connections, agent pools, and variable groups do not migrate automatically. Self-hosted agents must be re-registered to point to the new Services organization. External integrations (webhooks, API clients, IDE connections) must be updated to use the new dev.azure.com URLs. Plan a cutover window that accounts for DNS changes, client reconfiguration, and team communication. The production gotcha is underestimating the identity mapping effort and the pipeline reconfiguration work. Organizations with 10+ years of TFS history have thousands of unique identities from employees who have left, contractors, and service accounts. Each must be manually reviewed and mapped. Another common issue is TFVC workspace configuration: developers with local TFVC workspaces must recreate them pointing to the new Services instance. Pipeline migration requires recreating every Service Connection, variable group, and agent pool in the new organization, then updating pipeline YAML to reference the new resource names. Budget 2-4 weeks of effort beyond the actual data migration for this reconfiguration work.
Code Example
# Azure DevOps Data Migration — Complete Process # Step 1: Install the Data Migration Tool # Download from https://www.microsoft.com/download/details.aspx?id=54274 # Extract to C:\DataMigration # Step 2: Run validation against collection Migrator.exe validate /collection:http://tfs.internal:8080/tfs/DefaultCollection \ /tenantDomainName:bank-corp.onmicrosoft.com \ /outputPath:C:\Migration\Validation # Review validation results # C:\Migration\Validation\Results.json contains: # - Blocking issues (must fix before migration) # - Warnings (features that behave differently) # - Identity mapping file template # Step 3: Fix blocking issues # Example: Repository too large # git filter-branch to remove large files # Or: Move large binaries to Git LFS before migration # Step 4: Generate identity map Migrator.exe identityMap /collection:http://tfs.internal:8080/tfs/DefaultCollection \ /outputPath:C:\Migration\IdentityMap # Identity map file (IdentityMap.csv): # Source (AD),Target (Azure AD),Status # BANK\ramesh.a,[email protected],Matched # BANK\john.former,[email protected],NotFound ← must resolve # BANK\svc-build,[email protected],ServiceAccount # Step 5: Generate DACPAC export # Use SqlPackage.exe from SQL Server tools SqlPackage.exe /Action:Export \ /SourceServerName:"sql-server.internal" \ /SourceDatabaseName:"Tfs_DefaultCollection" \ /TargetFile:"C:\Migration\DefaultCollection.dacpac" \ /p:Storage=File # Step 6: Upload DACPAC to Azure blob storage # Microsoft provides a SAS token during import setup az storage blob upload \ --account-name importstorageaccount \ --container-name import \ --file C:\Migration\DefaultCollection.dacpac \ --name DefaultCollection.dacpac \ --sas-token "?sv=2021-06-08&ss=b&srt=co&sp=rwdlac..." # Step 7: Submit import request Migrator.exe import /collection:http://tfs.internal:8080/tfs/DefaultCollection \ /tenantDomainName:bank-corp.onmicrosoft.com \ /targetOrgName:bank-corp \ /identityMapFile:C:\Migration\IdentityMap.csv \ /dacpacFile:DefaultCollection.dacpac # Step 8: Monitor import progress # Check status at: https://dev.azure.com/bank-corp/_admin/_import # Status transitions: Queued → InProgress → Completed/Failed # Step 9: Post-migration validation # Verify repos az repos list --org https://dev.azure.com/bank-corp --project payments-platform # Verify work items preserved az boards query --org https://dev.azure.com/bank-corp \ --wiql "SELECT [System.Id] FROM workitems WHERE [System.TeamProject] = 'payments-platform'" \ --output table # Step 10: Reconfigure pipelines (these don't auto-migrate) # Create service connections az devops service-endpoint create \ --service-endpoint-configuration aws-connection.json \ --org https://dev.azure.com/bank-corp \ --project payments-platform # Re-register self-hosted agents ./config.sh --unattended \ --url https://dev.azure.com/bank-corp \ --auth pat --token $NEW_PAT \ --pool "Default" --agent "build-01" --replace
◈ Architecture Diagram
┌──────────────────────────────────────────────────────────┐ │ TFS/Server to Services Migration Flow │ │ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌─────────┐ │ │ │1.Validate│→ │2.Identity│→ │3.Export │→ │4.Upload │ │ │ │ (fix │ │ Map │ │ DACPAC │ │ to Blob│ │ │ │ issues) │ │ (AD→AAD)│ │ (SQL) │ │ Storage│ │ │ └──────────┘ └──────────┘ └──────────┘ └────┬────┘ │ │ │ │ │ ↓ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌─────────┐ │ │ │8.Cutover │← │7.Reconfig│← │6.Validate│← │5.Import │ │ │ │ (DNS, │ │ (Service│ │ (repos, │ │ (MSFT │ │ │ │ clients)│ │ Conns, │ │ WIs, │ │ process│ │ │ │ │ │ agents) │ │ history) │ │ queue) │ │ │ └──────────┘ └──────────┘ └──────────┘ └─────────┘ │ │ │ │ What migrates: What does NOT migrate: │ │ ├── Source code + hist ├── Service Connections │ │ ├── Work items + revs ├── Agent pools/agents │ │ ├── Git branches/tags ├── Variable groups │ │ ├── Build history ├── Extensions (reinstall) │ │ └── Test results └── Webhooks/integrations │ └──────────────────────────────────────────────────────────┘
Quick Answer
Upgrading TFS to Azure DevOps Server involves backing up databases, verifying hardware requirements, running the installer which performs an in-place upgrade of the application tier and database schema, then validating all collections, build agents, and extensions. The upgrade supports skipping versions (TFS 2018 directly to Server 2022) but requires careful pre-upgrade validation and rollback planning.
Detailed Answer
Think of upgrading TFS to Azure DevOps Server like renovating a house while people are still living in it. You need to photograph every room beforehand (backup), verify the new appliances fit the existing plumbing and wiring (compatibility checks), schedule the renovation during a weekend when disruption is minimal (maintenance window), perform the work (installer), verify everything works (validation), and keep the original photos in case you need to restore something (rollback plan). Skipping a version is like jumping from a 1990s kitchen directly to a 2024 design: possible because the renovation contractor handles all intermediate structural changes, but the transformation is more dramatic and testing more critical. The pre-upgrade phase is the most important and most frequently rushed. Begin by documenting your current environment: TFS version and update level, SQL Server version, Windows Server version, number of project collections, total database size, installed extensions, configured build agents, and any custom plugins or event handlers. Check the compatibility matrix: Azure DevOps Server 2022 requires SQL Server 2019 or 2022 and Windows Server 2019 or 2022. If your current SQL Server version is not supported, you must upgrade SQL Server first, which is a separate project with its own planning. Run the TFS upgrade readiness tool (included in the Azure DevOps Server installer) against your databases to identify any blocking issues like unsupported collation settings, deprecated features, or corrupted work item data. The backup strategy must be comprehensive and tested. Back up all collection databases, the configuration database, the warehouse database (if used), the reporting databases, and the file system cache. Do not rely solely on SQL Server backups: also export your build definitions, release definitions, extension configurations, and agent pool settings using the Azure DevOps CLI or REST API. These exports serve as documentation even if the upgrade succeeds, because they provide a reference point for validating that everything migrated correctly. Most importantly, test your restore process in a separate environment before the real upgrade. A backup you have never restored is a backup you cannot trust. The upgrade itself is surprisingly straightforward when prerequisites are met. Download the Azure DevOps Server 2022 installer, run it on the application tier server, and it detects the existing TFS installation. The wizard offers an upgrade path, validates the environment, and then performs the schema migration on each collection database. For large databases (500GB+), the schema migration can take several hours. The installer handles all intermediate version migrations: if you are upgrading from TFS 2018, it applies the schema changes for 2018→2019→2020→2022 sequentially. During this time, the server is offline. Plan your maintenance window based on database size: roughly 1 hour per 100GB is a conservative estimate, though actual times depend on SQL Server hardware. Post-upgrade validation is where most teams cut corners and regret it later. Verify that all project collections are online and accessible. Check that build agents reconnect (agents from TFS 2018 may need updating). Validate that XAML build definitions were preserved as read-only references. Test that Git and TFVC repositories are accessible with full history. Verify that work item queries, dashboards, and extensions function correctly. Run a sample build pipeline to confirm agents execute properly. Check that notification subscriptions still deliver emails. If you use the reporting warehouse or SharePoint integration, verify those connections. The production gotcha is the agents and extensions gap. Self-hosted build agents from TFS 2018 use an older agent version that may not be compatible with Azure DevOps Server 2022 features. You will likely need to deploy new agents or update existing ones. Extensions installed from the Visual Studio Marketplace may have version compatibility issues: some extensions that worked on TFS 2018 have been deprecated or replaced. Test all critical extensions in a pre-production upgrade before touching production. Another common issue is authentication: if you switch from NTLM to Kerberos or add Azure AD authentication during the upgrade, all existing PATs and service account connections need reconfiguration.
Code Example
# Pre-upgrade validation and backup procedure
# Step 1: Document current environment
Req -Method GET -Uri "http://tfs.internal:8080/tfs/_apis/projectCollections" \
-Headers @{Authorization="Basic $base64Pat"}
# Check TFS version
curl -u user:pat http://tfs.internal:8080/tfs/_apis/connectionData
# Look for: "releaseType":"Release", "version":"16.153.x" (TFS 2018)
# Step 2: Verify SQL Server compatibility
# Azure DevOps Server 2022 requires SQL Server 2019 or 2022
SELECT @@VERSION -- Check current SQL version
SELECT name, collation_name FROM sys.databases -- Verify collation
# Step 3: Backup all databases
-- SQL Server backup script for all TFS databases
BACKUP DATABASE [Tfs_Configuration]
TO DISK = 'E:\Backups\PreUpgrade\Tfs_Configuration.bak'
WITH COMPRESSION, CHECKSUM;
BACKUP DATABASE [Tfs_DefaultCollection]
TO DISK = 'E:\Backups\PreUpgrade\Tfs_DefaultCollection.bak'
WITH COMPRESSION, CHECKSUM;
BACKUP DATABASE [Tfs_Warehouse]
TO DISK = 'E:\Backups\PreUpgrade\Tfs_Warehouse.bak'
WITH COMPRESSION, CHECKSUM;
# Step 4: Export build definitions (for documentation)
az pipelines list --org http://tfs.internal:8080/tfs/DefaultCollection \
--project payments-platform --output json > build-definitions-backup.json
# Step 5: Run upgrade readiness check
# Launch Azure DevOps Server 2022 installer
# Select: "Upgrade" → "Pre-production upgrade validation"
# Or use command line:
# TfsConfig.exe preUpgrade /sqlInstance:SQLServer\Instance
# Step 6: Perform the upgrade (during maintenance window)
# Run installer on Application Tier server
# Installer detects existing TFS 2018/2019 installation
# Follow wizard: Upgrade → Select configuration database → Validate → Upgrade
# Step 7: Post-upgrade validation
# Verify collections are online
curl -u user:pat https://devops.internal:8080/tfs/_apis/projectCollections
# Verify agent pools
az pipelines agent list --pool-id 1 \
--org https://devops.internal:8080/tfs/DefaultCollection
# Update self-hosted agents to latest version
./config.sh --unattended \
--url https://devops.internal:8080/tfs/DefaultCollection \
--auth negotiate \
--pool "Default" \
--agent "build-agent-01" \
--replace
# Verify Git repositories are accessible
git clone https://devops.internal:8080/tfs/DefaultCollection/Project/_git/repo
# Step 8: Rollback procedure (if upgrade fails)
# Stop Azure DevOps Server services
# Restore SQL databases from pre-upgrade backups
# Reinstall previous TFS version pointing to restored databases
# Verify functionality
# Upgrade path reference:
# TFS 2018 → Azure DevOps Server 2022 (direct, skips 2019/2020)
# TFS 2017 → Azure DevOps Server 2022 (direct)
# TFS 2015 → TFS 2018 → Azure DevOps Server 2022 (two hops)
# TFS 2013 → TFS 2018 → Azure DevOps Server 2022 (two hops)◈ Architecture Diagram
┌──────────────────────────────────────────────────────────┐ │ TFS to Azure DevOps Server Upgrade Path │ │ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────┐ │ │ │ TFS 2015 │──→│ TFS 2018 │──→│ Server │──→│Server│ │ │ └──────────┘ └────┬─────┘ │ 2020 │ │ 2022 │ │ │ │ └──────────┘ └──────┘ │ │ │ ↑ ↑ │ │ └──────────────┴──────────────┘ │ │ (Direct upgrade supported) │ │ │ │ Upgrade Process: │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌─────────┐ │ │ │1. Backup │→ │2. Validate│→ │3. Upgrade│→ │4. Verify│ │ │ │ • SQL DBs│ │ • SQL ver │ │ • Run │ │ • Repos │ │ │ │ • Config │ │ • Win ver │ │ installer│ │ • Agents│ │ │ │ • Agents │ │ • Disk │ │ • Schema │ │ • Builds│ │ │ │ • Export │ │ • Extensions│ │ migrate│ │ • Exts │ │ │ └──────────┘ └──────────┘ └──────────┘ └─────────┘ │ │ │ │ Rollback: Restore SQL backups + reinstall previous ver │ └──────────────────────────────────────────────────────────┘