Azure DevOps Backup & Restore Extension
Enterprise-grade backup and restore solution for Azure DevOps organizations.
Protect your Azure DevOps investment with automated backups of Git repositories, build pipelines, work items, variables, and queries. Restore your resources quickly when needed.
🚀 Why Choose This Extension?
- ✅ Complete Protection - Backup all Azure DevOps resources in a single operation
- ✅ Lightning Fast - Incremental backups capture only changes since last backup
- ✅ Disaster Recovery Ready - Restore entire projects or specific resources on demand
- ✅ Pipeline Native - Fully automated within your Azure Pipelines
- ✅ Your Storage, Your Control - All backups are stored in your own storage location that you control
📦 What Gets Backed Up?
| Resource |
Full History |
Attachments |
Notes |
| Git Repositories |
✅ |
N/A |
All branches, tags, and commits |
| Pull Requests |
✅ |
N/A |
PR metadata, comments, reviews, status |
| Build Definitions |
✅ |
N/A |
Complete pipeline configurations |
| Build History |
✅ |
N/A |
Up to 100 builds per definition per run |
| Release Definitions |
✅ |
N/A |
Complete release pipeline configurations |
| Service Connections |
N/A |
N/A |
Connection metadata (credentials excluded) |
| Work Items |
✅ |
✅ |
All fields, links, and revisions |
| Pipeline Variables |
N/A |
N/A |
Variable groups (secrets excluded) |
| Shared Queries |
N/A |
N/A |
All folders and definitions |
| Boards |
N/A |
N/A |
Board configurations backed up fully; restore may be partial due to API limitations (custom columns) |
| Dashboards |
N/A |
N/A |
Dashboard widgets backed up; some complex widgets may not restore fully |
| Wiki |
✅ |
N/A |
Wiki pages with full content; page hierarchy preserved |
🎯 Key Features
Incremental Backups
Run daily incremental backups that only capture new or changed data since your last backup. Reduce backup time by 80% while maintaining complete data protection.
Dry-Run Mode
Preview exactly what will be restored before making any changes. Perfect for compliance, testing, and validation scenarios.
Selective Operations
Backup or restore only what you need. Choose specific components with simple checkbox options - select only Git, only Builds, or any combination you need.
Enterprise Logging
Comprehensive logging with verbose mode for troubleshooting, auditing, and compliance requirements.
📋 Available Pipeline Tasks
1. Azure DevOps Backup Task
Back up all or selected Azure DevOps resources with flexible filtering options.
Key Parameters:
- Incremental Mode - Only backup new/changed resources
- Project Filter - Backup specific projects only
- Component Selection - Choose all components or select specific ones (Git, Builds, Releases, Work Items, Variables, Queries)
- Time Range - Limit build history to days or count
- Verbose Logging - Detailed operation logs
2. Azure DevOps Restore Task
Restore all or selected Azure DevOps resources with granular filtering options.
Key Parameters:
- Project Filter - Restore specific projects only
- Component Selection - Choose all components or select specific ones (Git, Builds, Releases, Work Items, Variables, Queries)
- Resource Filtering - Restore specific repositories, build definitions, release definitions, work item IDs, or query folders
- Target Project - Optionally restore to a different project (single source project only)
- Dry Run - Preview changes without applying them
- Verbose Logging - Detailed operation logs
🔧 Quick Start
Step 1: Set Up Variable Group
Create a variable group named "ADO Backup Restore" with:
Backup.LicenseKey [Secret] Your license key
Backup.AdoPat.RO [Secret] Read-only PAT for backups
Backup.AdoPat.RW [Secret] Read-write PAT for restores
Backup.Root [Plain] Backup directory path
Step 2: Add Backup Task to Pipeline
- task: AzureDevOpsBackupTask@0
displayName: 'Daily Incremental Backup'
env:
ADOBACKUP_LICENSE_KEY: $(Backup.LicenseKey)
inputs:
Pat: '$(Backup.AdoPat.RO)'
BackupRoot: '$(Backup.Root)'
Verbose: true
BackupMode: 'Incremental'
Step 3: Schedule Automated Backups
schedules:
- cron: "0 2 * * *"
displayName: Daily Backup at 2 AM
branches:
include:
- main
🔄 Component Selection
The extension uses include-based flags for intuitive component selection:
- BackupAll / RestoreAll checkbox (default: ✅ checked) - Backup/restore all components
- When unchecked, use Include checkboxes to select specific components:
- ✅ Include Git Repositories
- ✅ Include Pull Requests
- ✅ Include Build Definitions
- ✅ Include Release Definitions
- ✅ Include Service Connections
- ✅ Include Work Items
- ✅ Include Pipeline Variables
- ✅ Include Shared Queries
- ✅ Include Task Groups
- ✅ Include Boards
- ✅ Include Dashboards
- ✅ Include Wikis
Benefits
- Intuitive: Check what you want to include
- Simple: Single checkbox for Git-only backup
- Clear: Intent is obvious at a glance
💡 Usage Examples
Example 1: Complete Daily Backup
Backup everything with incremental mode for fast, efficient backups:
name: DailyBackup_$(Date:yyyyMMdd)
trigger: none
schedules:
- cron: "0 2 * * *"
displayName: Daily Backup
branches:
include:
- main
pool:
vmImage: 'windows-latest'
variables:
- group: 'ADO Backup Restore'
jobs:
- job: BackupJob
displayName: 'Backup Azure DevOps'
timeoutInMinutes: 120
steps:
- task: AzureDevOpsBackupTask@0
displayName: 'Incremental Backup'
env:
ADOBACKUP_LICENSE_KEY: $(Backup.LicenseKey)
inputs:
Pat: '$(Backup.AdoPat.RO)'
BackupRoot: '$(Backup.Root)'
Projects: '' # Empty = all projects
Verbose: true
BackupMode: 'Incremental'
BackupAll: true # Backup all components (default)
- task: PublishBuildArtifacts@1
displayName: 'Upload Backup Logs'
condition: always()
inputs:
PathtoPublish: '$(Backup.Root)/logs'
ArtifactName: 'BackupLogs-$(Build.BuildNumber)'
continueOnError: true
Example 2: Selective Backup (Git Repositories Only)
Backup only Git repositories when you have separate solutions for other resources:
- task: AzureDevOpsBackupTask@0
displayName: 'Backup Git Repositories Only'
env:
ADOBACKUP_LICENSE_KEY: $(Backup.LicenseKey)
inputs:
Pat: '$(Backup.AdoPat.RO)'
BackupRoot: '$(Backup.Root)'
Projects: 'Project1,Project2' # Specific projects
Verbose: true
BackupMode: 'Full'
BackupAll: false # Selective backup
IncludeGit: true # Only include Git repositories
GitRepositories: 'Repo1,Repo2' # Specific repositories
Example 3: Disaster Recovery - Dry Run
Preview restore operations before executing for disaster recovery validation:
- task: AzureDevOpsRestoreTask@0
displayName: 'Disaster Recovery Dry Run'
env:
ADOBACKUP_LICENSE_KEY: $(Backup.LicenseKey)
inputs:
Pat: '$(Backup.AdoPat.RW)'
BackupRoot: '$(Backup.Root)'
Projects: 'CriticalProject'
DryRun: true # Preview only, no changes
Verbose: true
RestoreAll: true # Restore all components (default)
Example 4: Selective Restore (Builds Only)
Restore only build definitions after configuration changes:
- task: AzureDevOpsRestoreTask@0
displayName: 'Restore Build Definitions'
env:
ADOBACKUP_LICENSE_KEY: $(Backup.LicenseKey)
inputs:
Pat: '$(Backup.AdoPat.RW)'
BackupRoot: '$(Backup.Root)'
Projects: 'MyProject'
# Selective restore - only builds
RestoreAll: false
IncludeBuilds: true # Only include builds
BuildDefinitions: '1,2,5' # Specific build definition IDs
DryRun: false
Verbose: true
Example 5: Weekly Full + Daily Incremental Strategy
Combine full and incremental backups for optimal protection:
schedules:
# Full backup every Sunday
- cron: "0 1 * * 0"
displayName: Weekly Full Backup
branches:
include:
- main
# Incremental backup weekdays
- cron: "0 2 * * 1-6"
displayName: Daily Incremental Backup
branches:
include:
- main
jobs:
- job: BackupJob
steps:
- powershell: |
$isFullBackup = (Get-Date).DayOfWeek -eq 'Sunday'
Write-Host "##vso[task.setvariable variable=BackupMode]$(if ($isFullBackup) {'Full'} else {'Incremental'})"
displayName: 'Determine Backup Mode'
- task: AzureDevOpsBackupTask@0
displayName: '$(BackupMode) Backup'
env:
ADOBACKUP_LICENSE_KEY: $(Backup.LicenseKey)
inputs:
Pat: '$(Backup.AdoPat.RO)'
BackupRoot: '$(Backup.Root)'
BackupMode: '$(BackupMode)'
Verbose: true
🔐 Security Best Practices
Use Separate PAT Tokens
For Backups (Read-Only):
- Code: Read
- Build: Read
- Work Items: Read
- Variable Groups: Read
- Service Connections: Read
- Project and Team: Read
For Restores (Read-Write):
- Code: Read & Write
- Build: Read & Write
- Work Items: Read & Write
- Variable Groups: Read & Write
- Service Connections: Read & Write
- Project and Team: Read & Write
Secure Storage
- Store PAT tokens as secret variables in variable groups
- Use Azure Key Vault for enterprise credential management
- Rotate tokens regularly (90-day expiration recommended)
- Never commit credentials to source control
Backup Encryption
- Use encrypted storage for backup directories
- Enable BitLocker on backup drives (Windows)
- Use Azure Blob Storage with encryption at rest
- Implement access controls on backup locations
🛠️ Prerequisites
- Azure DevOps organization with appropriate permissions
- Personal Access Token (PAT) with required scopes
- Backup storage location (local path, network share, or cloud storage)
- Valid license key for production use
⚠️ Limitations & Known Issues
Understanding the limitations helps you plan your backup and restore strategy effectively. Most limitations are due to Azure DevOps API constraints or Git protocol requirements.
| Component |
Limitation |
Impact |
Workaround/Notes |
| Work Items |
Restores to same project only |
Work items restored with same IDs |
Deleted work items are recreated with new IDs if needed |
| Work Items |
Restore updates existing work items without adding comments |
No audit trail of restore operation |
Work item history shows field changes but not restore event |
| Work Items |
Incremental backup uses daily granularity, not exact timestamp |
May backup some items twice if run multiple times per day |
Incremental mode tracks last backup date (YYYY-MM-DD), not time |
| Work Items |
Deleted work items are recreated with new IDs during restore |
Original IDs cannot be preserved |
Links and relationships are recreated with new IDs |
| Queries |
Query definitions restored/updated as-is |
Existing queries are updated with backup data |
Verify area paths and iteration paths exist in project before restore |
| Pull Requests |
Full PR record is restored (title, description, comments, reviews, status, votes) |
Code changes already exist in Git history from merge |
PRs are recreated with all discussion and review data |
| Pull Requests |
PR IDs preserved only when restoring to same project |
Cross-project restore may create new IDs |
Work item links in PRs are preserved if work items exist |
| Service Connections |
Secrets/credentials are NOT backed up |
Credentials will be lost |
Must manually re-enter secrets after restore |
| Service Connections |
Pipeline authorizations must be reconfigured |
Pipelines won't have access until reauthorized |
Manually authorize pipelines to use connections after restore |
| Git Repositories |
Non-fast-forward pushes fail if remote history diverged |
Restore fails if repository changed after backup |
See Git-specific limitations below |
| Azure DevOps API |
Rate limiting varies by organization tier |
Backup may be throttled on high-volume operations |
Reduce MaxParallelism, space out backups, or contact Microsoft for limit increase |
| Build History |
Maximum 100 builds per definition per backup run |
Can't backup more than 100 builds in single run |
Use --days parameter with incremental mode to capture builds over time, build history is kept locally for reference and cannot be restored due to Azure DevOps limitations |
| Build Definitions |
Existing definitions are updated during restore |
Definition configuration is overwritten |
Review changes before restore; use --dry-run to preview |
| Variable Groups |
Passwords/secrets are NOT backed up |
Secret values will be lost |
Document secret variables separately; re-enter after restore |
| Variable Groups |
Existing variable groups are updated during restore |
Variable group values are overwritten (except secrets) |
Secrets must be manually re-entered after restore |
| Boards |
Custom columns may not restore correctly |
Azure DevOps API rejects certain column configurations |
Board is restored but some columns may be missing; verify after restore |
| Boards |
Board auto-creation not supported |
Board must exist in target project before restore |
Boards are updated, not created; ensure target boards exist |
| Boards |
Column state mappings may be rejected by API |
API returns "Value cannot be null. Parameter name: options" |
Backup preserved for reference; manual board configuration may be needed |
| Boards |
WIP limits may not be preserved |
Column WIP limits may revert to defaults |
Verify WIP limits after restore; adjust manually if needed |
| Boards |
Card styling/colors may not be preserved |
Custom card styles may revert to defaults |
Cosmetic only; reconfigure card styles after restore if needed |
| Dashboards |
Widget configurations may not restore fully |
Some widget types have API limitations |
Dashboard created but some widgets may need manual reconfiguration |
| Wiki |
Empty wikis restore as empty |
Wiki structure restored but no pages if backup had none |
Expected behavior; add pages as needed |
Git-Specific Limitations
| Scenario |
Issue |
Error Message |
Solution |
| Diverged History |
Remote repository has commits not in backup |
NonFastForwardException: cannot push because a reference that you are trying to update on the remote contains commits that are not present locally |
Option 1: Force push (loses remote commits) Option 2: Manually merge changes Option 3: Delete remote repo and restore fresh |
| Branch Protection |
Branch policies prevent force push |
Push fails due to branch policies |
Temporarily disable branch policies during restore |
| Large Repositories |
Git clone/push timeout on repos >50GB |
Operation timeout or memory errors |
Increase timeout, use --MaxParallelism 1 for large repos |
| LFS Objects |
Git LFS files require separate authentication |
LFS files may not restore correctly |
Ensure LFS credentials are configured |
Security Limitations
| Feature |
Limitation |
Recommendation |
| Secret Variables |
Pipeline variable secrets are NOT backed up |
Document secrets separately; use Azure Key Vault |
| Service Connection Secrets |
Service connection credentials/secrets are NOT backed up |
Document secrets separately; re-enter after restore |
| PAT Tokens |
PAT tokens used in pipelines are NOT backed up |
Re-configure service connections after restore |
| SSH Keys |
Git SSH keys are NOT backed up |
Re-upload SSH keys to target organization |
Restore Behavior & Important Notes
| Component |
Behavior |
Important Notes |
| Work Items |
Updates existing work item if found by ID |
No comments added to work item history about restore operation |
| Work Items |
Creates new work item if original was deleted |
New ID assigned; relationships recreated |
| Build Definitions |
Updates existing definition if found by ID |
Definition is updated with backup data |
| Build Definitions |
Creates new definition if doesn't exist |
New definition created with original configuration |
| Variable Groups |
Updates existing group if found by name |
Group is updated with backup data (except secrets) |
| Variable Groups |
Creates new group if doesn't exist |
New variable group created |
| Variable Groups |
Secret values are NOT restored |
Passwords/secrets are not backed up; must be re-entered manually |
| Service Connections |
Updates existing connection if found by name |
Connection metadata updated (except secrets) |
| Service Connections |
Secret values/credentials are NOT restored |
Must manually re-enter passwords, keys, certificates after restore |
| Service Connections |
Pipeline authorizations are NOT restored |
Must manually authorize pipelines to use connections |
| Pull Requests |
Restores complete PR with title, description, comments, reviews, status, votes |
Code changes already in Git from original merge |
| Pull Requests |
Work item links preserved if work items exist |
Broken links if work items not restored |
| Pull Requests |
PR IDs preserved when restoring to same project |
Cross-project restore may assign new IDs |
| Queries |
Updates existing query if found by ID |
Query definition is overwritten with backup data |
| Queries |
Creates new query if doesn't exist |
New query created with original structure |
| Git Repositories |
Uses force push by default |
Warning: Overwrites remote history; ensure backup is correct version |
| Boards |
Updates existing board if found |
Board structure updated but custom columns may fail due to API limitations |
| Boards |
Boards are NOT auto-created |
Board must exist in target project; cannot create new boards via API |
| Boards |
Column configurations may be partially restored |
Standard columns restore OK; custom columns may be rejected by Azure DevOps API |
| Boards |
Swimlanes (rows) restore more reliably than columns |
Rows have fewer API constraints than columns |
| Dashboards |
Updates existing dashboard if found |
Dashboard structure updated; some widget types may have limitations |
| Dashboards |
Dashboards are NOT auto-created |
Dashboard must exist in target; cannot create new dashboards via API |
| Dashboards |
Widget counts may differ after restore |
Some complex widget configurations may not be supported by API |
| Wiki |
Updates existing wiki if found |
Wiki pages restored with content |
| Wiki |
Empty wikis restore as empty |
Wikis with zero pages remain empty after restore |
| Wiki |
Page hierarchy preserved |
Page paths and structure maintained during restore |
Best Practices to Avoid Issues
✅ DO:
- Test restores regularly to verify backup integrity
- Use
--dry-run before actual restore to preview changes
- Document all secret variables and service connections separately
- Disable branch policies temporarily during Git restore
- Understand that restore OVERWRITES existing resources - backup important configurations before restore
❌ DON'T:
- Restore to repositories that have diverged from backup without planning
- Rely on backup for secret variables - they are NOT backed up
- Expect work item restore to add comments about the restore operation
- Run incremental work items backup more than once per day (redundant)
- Assume existing build definitions or variable groups will be preserved - they will be overwritten with backup data
- Restore without using
--dry-run first to understand what will be changed
Getting Help with Limitations
If you encounter issues related to these limitations:
- Review this table for known workarounds
- Check the Troubleshooting Guidede
- Contact support@lamdat.com with:
- Specific limitation you're facing
- Your use case and requirements
- Logs showing the error (if applicable)
Note: Some limitations are Azure DevOps API constraints that cannot be worked around by the extension. We're actively working with Microsoft and the community to improve these capabilities where possible.
- Small organization (1-5 projects): 5-30 minutes
- Medium organization (5-20 projects): 30-120 minutes
- Large organization (20+ projects): 2-8 hours
- Incremental backups: 50-80% faster than full backups
Azure DevOps API Limits
- Maximum 100 builds per definition per backup run (API limitation)
- Rate limiting automatically handled with retry logic
- Configurable parallelism (default: 4, max recommended: 12)
Storage Requirements
- Git repositories: ~1.2x current size
- Build history: ~1-5 MB per build
- Work items: ~10-50 KB per item
- Plan for 2x estimated size for growth
🎓 Additional Resources
Documentation
Support
🗺️ Roadmap
We're committed to continuously improving the Azure DevOps Backup & Restore Extension. Here's what's available and coming next:
✅ Version 0.9 - Now Available!
Boards & Backlogs Backup & Restore
Complete backup and restore of Azure Boards configurations:
- ✅ Board columns and definitions
- ✅ Swimlanes (Rows)
- ✅ Card styles and rules
- ✅ Board settings and permissions
- ✅ Team-scoped board configurations
Use Case: Preserve complex board configurations, replicate team processes across projects, recover from accidental configuration changes.
Task Groups Backup & Restore
Complete backup and restore of pipeline task groups:
- ✅ Task group definitions and metadata
- ✅ Task steps and configurations
- ✅ Input parameters and variables
- ✅ Cross-project restore support
- ✅ Update existing task groups by name
- ⚠️ Note: Task group IDs change during restore
Pull Request Backup & Restore
Complete backup of pull request data including:
- ✅ PR metadata (title, description, source/target branches)
- ✅ PR comments and discussions
- ✅ Code review comments with file/line context
- ✅ PR status and completion history
- ✅ Reviewer information and vote history
- ✅ Associated work items and commits
Use Case: Preserve code review history, maintain compliance records, restore PR discussions after accidental deletions.
Service Connection Backup & Restore
Backup of service connection configurations:
- ✅ Service connection metadata and settings
- ✅ Connection type and configuration
- ✅ Project associations
- ⚠️ Note: Credentials/secrets must be re-entered manually after restore
Use Case: Document service connection configurations, restore connection settings after migration or disaster recovery.
🚀 Coming Soon
Advanced ALM Features
Backup of Azure DevOps planning and tracking features:
Areas & Iterations
- ✨ Team areas and area paths
- ✨ Iteration schedules and dates
- ✨ Team capacity planning data
- ✨ Area permissions and security settings
Dashboards
- ✨ Dashboard definitions and layouts
- ✨ Widget configurations
- ✨ Chart settings and queries
- ✨ Custom dashboard templates
- ✨ Team and project dashboards
🔮 Future Releases
Release Management & Pipelines
- ✨ Release pipeline definitions (Classic)
- ✨ Release history and deployment logs
- ✨ Stage configurations and approvals
- ✨ Release gates and conditions
- ✨ Environment configurations
- ✨ Service connections and endpoints
- ✨ Agent pool configurations
Test Plans & Suites
- ✨ Test plans and test suites
- ✨ Test cases with steps and attachments
- ✨ Test runs and results
- ✨ Test configurations
- ✨ Manual and automated test associations
- ✨ Test parameters and shared steps
Wiki & Documentation
- ✨ Wiki pages and hierarchy
- ✨ Wiki attachments and images
- ✨ Page history and revisions
- ✨ Wiki permissions
- ✨ Project vs. Code wikis
Artifacts & Packages
- ✨ Azure Artifacts feed configurations
- ✨ Package metadata and versions
- ✨ Feed permissions and views
- ✨ Upstream sources
- ✨ Retention policies
Team & Security Settings
✨ Team definitions and members
✨ Security groups and permissions
✨ Project-level security settings
✨ Repository permissions
✨ Branch policies and security
✨ Service principal configurations
💬 Feature Requests
We value your feedback! Help us prioritize the roadmap:
- Vote on features: Contact support@lamdat.com with your top priorities
- Request new features: Describe your use case and we'll consider it for the roadmap
- Beta testing: Sign up for early access to preview features
🎯 Commitment to Excellence
Our roadmap is driven by:
- Customer feedback - Your needs shape our priorities
- Enterprise requirements - SOC 2, GDPR, and compliance standards
- Best practices - Industry-standard disaster recovery patterns
- Performance - Continuous optimization for large organizations
- Security - Enterprise-grade security and encryption
Want to influence the roadmap? Contact us at support@lamdat.com or provide feedback through the marketplace.
💼 License
This extension requires a valid license key for production use. Trial licenses available for evaluation.
Contact: Lamdat
Email: support@lamdat.com
Website: [Coming Soon]
🌟 Why Lamdat?
Lamdat specializes in enterprise Azure DevOps solutions, providing tools that protect your investment and ensure business continuity. Our backup and restore extension is trusted by organizations worldwide to safeguard their most critical development assets.
Ready to protect your Azure DevOps organization?
- Install the extension from the marketplace
- Configure your variable group with credentials
- Add backup task to your pipeline
- Schedule automated backups
- Sleep better knowing your data is safe
Questions? Contact support@lamdat.com
Copyright © 2025 Lamdat. All rights reserved.
Azure DevOps and Visual Studio are trademarks of Microsoft Corporation.