How I Used Azure File Sync During a Large Migration Project
Azure File Sync was not the tool I reached for first on this migration. It became the right tool once I understood what the project actually needed: zero-downtime data movement while users kept working, cloud tiering to free local disk on branch servers, and a single source of truth in Azure before the on-premises servers were decommissioned. Here is exactly how I deployed it, configured it, and used it across a six-site migration.
The Project: Six Sites, Twelve File Servers, One Source of Truth
The client was a professional services group with a headquarters in London and five branch offices across the UK. Each office had its own Windows file server with its own local shares. Nobody knew for certain which server had the authoritative copy of any given file — different branches had been independently creating and modifying files for years, with no replication between them. The IT team's description was: "we have twelve servers and twelve versions of the truth, and we need one." The migration brief was to consolidate everything into Azure Files, retire the on-premises servers, and give each branch office local-speed access to shared data without requiring them to traverse the WAN to London every time someone opened a document.
That last requirement — local-speed access at branch offices without WAN traversal — is the one that made Azure File Sync the right tool. It is not the right tool for every migration, and I will be specific about why I chose it here and where it does not belong. But for this project, it solved the hardest problem in the brief: how do you give 320 users across six offices fast local access to a single shared file repository, without keeping twelve file servers running indefinitely?
Why Azure File Sync — and Why Not Something Else
Before getting into the configuration, I want to be specific about why Azure File Sync was the right tool for this project — because it is not the right tool for every migration, and confusing the two cases leads to over-engineering.
The core requirement that made AFS the correct choice was ongoing hybrid access after migration. The branch offices needed local-speed access to files. WAN traversal to Azure Files from a Manchester office over a 50 Mbps MPLS link would have been unacceptably slow for users who were used to 10 Gbps LAN access to a local file server. AFS solves this by caching the most recently accessed files locally — users get LAN speed for hot files and transparent cloud recall for cold ones. The file appears on the local server. Users never know whether it is cached or tiered.
The secondary requirement was zero-downtime data movement. With twelve file servers and 320 active users, a scheduled downtime window large enough to copy all the data was not realistic. AFS syncs data continuously in the background while users keep working. The final cutover is a DNS/DFS-N change — not a maintenance window.
| Requirement | Azure File Sync | RoboCopy + Azure Files Direct |
|---|---|---|
| Zero-downtime migration while users work | ✓ Syncs continuously in background | ✗ Requires cutover window |
| Local-speed branch office access post-migration | ✓ Cloud tiering caches hot files locally | ✗ All access via WAN after migration |
| Single source of truth across all sites | ✓ Azure Files is the authoritative hub | ✓ If each site copies to same share |
| ACL preservation during migration | ✓ Full fidelity — syncs NTFS ACLs | ✓ With /COPY:DATSO flag |
| Ongoing hybrid sync needed post-migration | ✓ Core AFS capability | ✗ Manual re-runs required |
| Branch office decommission planned >6 months | ✓ AFS cache can run indefinitely | ✗ Direct Azure Files mount is simpler |
| Suitable when no ongoing hybrid needed | ~ Over-engineered for one-time migration | ✓ Simpler and cheaper |
The Azure File Sync Resource Model — What You Are Actually Building
Before touching the portal, the resource hierarchy must be understood. Azure File Sync adds three resource types on top of the Azure Files storage account: the Storage Sync Service, Sync Groups, and Server Endpoints. Getting the hierarchy wrong — particularly creating the Storage Sync Service in the wrong region — requires a full rebuild.
Deploying Azure File Sync: The Exact Steps I Followed
This is the deployment sequence for the project, written in the order I executed it. The order matters — particularly the instruction not to enable cloud tiering on the first server endpoint during migration. That is a deliberate sequencing decision, not an omission.
Create the Storage Sync Service in the same region as your storage account
Navigate to Create a resource and search for Azure File Sync. Select Storage Sync Service and select Create. Set the resource group, region, and name. The region must match the region of your Azure Files storage account exactly — this constraint cannot be changed after creation. I used the naming convention sss-corp-files-uksouth for clarity. One Storage Sync Service per region is sufficient for most deployments. Create it before creating any sync groups.
Create a sync group — one per file share you are migrating
Inside the Storage Sync Service, navigate to Sync groups → Add sync group. Name it clearly — I used the share name as the sync group name: sg-projects, sg-shared, sg-finance and so on. Select the storage account and the specific Azure file share this sync group will manage. This creates the cloud endpoint — the Azure file share becomes the authoritative data source for the group. Each sync group manages exactly one cloud endpoint (one Azure file share). Create one sync group per share.
Install the Azure File Sync agent on the first server — the migration source
Download the Azure File Sync agent from the Microsoft Download Centre. As of June 2026, the supported version is v22.3.0.0 (released April 17, 2026). The agent consists of two components: FileSyncSvc.exe (the background sync service) and StorageSync.sys (the file system filter that enables cloud tiering). Install on Windows Server 2016, 2019, 2022, or 2025. Run Windows Update before installing — the agent requires the server to be current. Restart after installation.
For this project, the first server to receive the agent was the HQ file server — the one with the most complete and authoritative copy of the shared data.
Invoke-WebRequest -Uri $agentUrl -OutFile "$env:TEMP\StorageSyncAgent.msi"
Start-Process msiexec.exe -ArgumentList "/i `"$env:TEMP\StorageSyncAgent.msi`" /quiet" -Wait
# Verify the agent version after installation Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Azure\StorageSync" | Select-Object AgentVersion
# Check agent service is running Get-Service -Name FileSyncSvc | Select-Object Name, Status
# Expected: Name=FileSyncSvc Status=Running
# Run the AFS evaluation tool to check for compatibility issues before registering Invoke-AzStorageSyncCompatibilityCheck -Path D:\Data -Credential (Get-Credential)
Register the server with the Storage Sync Service
After agent installation, the Server Registration wizard opens automatically. If it does not, run C:\Program Files\Azure\StorageSyncAgent\ServerRegistration.exe. Sign in with an Azure account that has Contributor rights to the Storage Sync Service. Select the correct subscription, resource group, and Storage Sync Service. Select Register. Registration creates a trust relationship between the server and the Storage Sync Service — the server now appears in the Storage Sync Service as a registered server. Verify the registration appears in the Azure portal before proceeding to create server endpoints.
Create the first server endpoint — cloud tiering OFF for the migration phase
In the Azure portal, navigate to the sync group and select Add server endpoint. Select the registered server. Enter the path to the folder on the server you are migrating — for example D:\Data\Finance. This is the most important configuration decision in the entire deployment:
Do not enable cloud tiering on the first server endpoint during the migration phase. If cloud tiering is enabled while the initial sync is uploading data, the tiering algorithm may tier files before they have fully synced, causing recall traffic and slowing the upload significantly. Keep cloud tiering disabled until the initial sync is complete and verified. You enable it afterwards.
Set Initial Sync mode to Merge (the default) — this merges the server content with whatever is already in the Azure file share. If the Azure file share is empty (which it should be at this point), Merge is identical to a full upload.
Monitor the initial sync — do not proceed to branch offices until complete
The initial sync uploads everything from the first server to Azure Files. For this project, the HQ server had 8TB across its shares — the initial upload took 11 days at 500 Mbps with business-hours throttling. Monitor progress in the Storage Sync Service portal: navigate to Sync groups → [group name] → Server endpoints → [server name] → Sync activity. Alternatively, use PowerShell to query sync status.
# Get sync status for a specific server endpoint $syncStatus = Get-AzStorageSyncServerEndpoint `
-ResourceGroupName "rg-filesync-prod" `
-StorageSyncServiceName "sss-corp-files-uksouth" `
-SyncGroupName "sg-finance"
$syncStatus | Select-Object `
ServerEndpointName,
@{N="SyncState";E={$_.SyncStatus.CombinedHealth}},
@{N="FilesNotSyncing";E={$_.SyncStatus.FilesNotSyncingCount}},
@{N="UploadProgress";E={$_.SyncStatus.SyncActivity.UploadedItemCount}}
# Check for sync errors — run this daily during initial upload Get-AzStorageSyncServerEndpoint -ResourceGroupName "rg-filesync-prod" `
-StorageSyncServiceName "sss-corp-files-uksouth" `
-SyncGroupName "sg-finance" | `
Select-Object -ExpandProperty SyncStatus | `
Select-Object CombinedHealth, FilesNotSyncingCount, LastSyncResult
# Expected: CombinedHealth = Healthy · FilesNotSyncingCount = 0
Enabling Cloud Tiering After the Initial Sync — The Two Policies
Once the initial sync from the HQ server to Azure Files was complete and verified, I enabled cloud tiering on the HQ server endpoint. Cloud tiering is what makes AFS valuable for branch office deployments with limited local storage — it keeps only hot files on the local server and moves cold files to Azure Files, where they appear as stub files that are recalled on access.
Cloud tiering is controlled by two independent policies. Both can be active simultaneously and the more aggressive policy wins at any point in time.
Enable cloud tiering on the HQ server endpoint after initial sync is complete
Navigate to the server endpoint in the Azure portal. Under Cloud Tiering, toggle to Enabled. Set Volume Free Space Policy to 80% — this reserves 80% of the local volume as free space, meaning only the hottest 20% of the total dataset is cached locally. Set the Date Policy to 30 days — files not accessed in 30 days are tiered regardless of disk pressure. Click Save. The tiering algorithm begins running immediately and continues in the background as a low-priority process.
Install the agent and create server endpoints on all branch office servers
Repeat the agent installation, server registration, and server endpoint creation for each branch office server. For branch offices (Manchester, Birmingham, Bristol, Leeds, Edinburgh), the Initial Download setting is important — for the second and subsequent server endpoints in a sync group, the default is to download the namespace first (files appear as stubs) and then download content on demand or via background recall. This is the correct setting for branch offices with limited WAN bandwidth — users see all files immediately but content only downloads when accessed.
Enable cloud tiering on branch office endpoints immediately — unlike the migration source server, branch offices benefit from tiering from day one since they have limited local storage and primarily need access to recently active project files.
New-AzStorageSyncServerEndpoint `
-ResourceGroupName "rg-filesync-prod" `
-StorageSyncServiceName "sss-corp-files-uksouth" `
-SyncGroupName "sg-projects" `
-ServerResourceId "/subscriptions/.../resourceGroups/.../providers/Microsoft.StorageSync/storageSyncServices/sss-corp-files-uksouth/registeredServers/FS-MCR-01" `
-ServerLocalPath "D:\Data\Projects" `
-CloudTiering # Enable cloud tiering
-VolumeFreeSpacePercent 80 ` # Keep 80% of volume free — only 20% cached locally
-TierFilesOlderThanDays 30 # Tier files not accessed in 30 days
# Verify endpoint was created successfully Get-AzStorageSyncServerEndpoint -ResourceGroupName "rg-filesync-prod" `
-StorageSyncServiceName "sss-corp-files-uksouth" `
-SyncGroupName "sg-projects" | Select-Object ServerEndpointName, CloudTieringStatus
Three Configuration Mistakes That Taught Me the Most
Configuring Antivirus to Skip Tiered Files — the Critical Step Nobody Mentions
Tiered files have the Windows attribute FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS set. Any process that reads a tiered file — including antivirus scanners — will trigger a recall from Azure. During an overnight antivirus scan across 150,000 tiered files, this can generate significant egress charges and fill the local disk completely, stopping sync.
Microsoft Defender Antivirus and System Center Endpoint Protection automatically skip reading files with this attribute during on-demand scans. If you are running any other antivirus product, check whether it honours this attribute before enabling cloud tiering on branch servers. Configure any non-Defender product to exclude files with FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS from scan operations. This is not optional — it cost us £380 in one night before we caught it.
The Cutover: How We Retired the Old Servers Without Downtime
The cutover for an AFS-based migration is fundamentally different from a RoboCopy-based migration. There is no final data copy — AFS has been continuously syncing the data for weeks. The cutover is purely a namespace change: redirect the DFS-N target from the old Windows file server to the Windows Server now acting as the AFS cache. Users never lose access, because the AFS server has been serving the same data all along.
Confirm all server endpoints are fully synced before cutover day
Run the PowerShell sync health check across all sync groups 48 hours before the planned cutover. Confirm CombinedHealth = Healthy and FilesNotSyncingCount = 0 for every server endpoint in every sync group. If any endpoint shows pending uploads or sync errors, resolve them before proceeding. Do not execute a cutover with outstanding sync errors — the cutover makes the AFS server the authoritative path, and any unsynced files on the old server become inaccessible.
Set the old file server to read-only — do not disable it yet
Set the legacy file server shares to read-only. This prevents new writes to the old server during the cutover window. Users can still read files. Wait 60 minutes and run a final sync health check — if any uploads were still in progress when you set read-only, they will complete and sync to Azure Files within this window. Confirm sync is fully caught up before proceeding to the DFS-N change.
Execute the DFS-N redirect from legacy file server to AFS cache server
Execute the DFS-N target change using PowerShell — setting the old server target to offline and the new AFS server target to active. The AFS cache server path contains exactly the same data as the Azure file share (hot files locally, cold files as stubs). Users are immediately redirected with no interruption to access.
-TargetPath "\\FS-HQ-01\Projects" `
-State Offline
# Add the AFS cache server as the new active target New-DfsnFolderTarget -Path "\\corp.local\files\Projects" `
-TargetPath "\\AFS-HQ-01\Projects" ` # AFS cache server — has agent installed
-State Online
# Verify: confirm only the AFS server is active Get-DfsnFolderTarget -Path "\\corp.local\files\Projects" | `
Select-Object TargetPath, State
# Expected output: # TargetPath State # ---------- ----- # \\FS-HQ-01\Projects Offline ← old server, offline # \\AFS-HQ-01\Projects Online ← AFS cache server, active
Monitoring AFS Health After Cutover — What to Watch
After cutover, ongoing monitoring keeps the AFS deployment healthy. The three most important metrics to watch are sync health (is everything staying in sync?), tiering activity (are files tiering and recalling as expected?), and recall latency (are users experiencing acceptable wait times when opening tiered files?).
# Check all server endpoints across all sync groups $allGroups = Get-AzStorageSyncGroup -ParentObject $sss
foreach ($group in $allGroups) {
$endpoints = Get-AzStorageSyncServerEndpoint -ParentObject $group
foreach ($ep in $endpoints) {
[PSCustomObject]@{
SyncGroup = $group.SyncGroupName
Server = $ep.ServerEndpointName
Health = $ep.SyncStatus.CombinedHealth
NotSyncing = $ep.SyncStatus.FilesNotSyncingCount
LastSync = $ep.SyncStatus.LastSyncResult
}
}
} | Format-Table -AutoSize
# Check cloud tiering health on a specific server Invoke-AzStorageSyncChangeDetection `
-ResourceGroupName "rg-filesync-prod" `
-StorageSyncServiceName "sss-corp-files-uksouth" `
-SyncGroupName "sg-projects" `
-CloudEndpointName "cloud-endpoint-projects"