How We Migrated 15TB from QNAP NAS to Azure Files: A Real-World Case Study
The planning decisions, the RoboCopy commands that preserved full fidelity, the ACL problem we did not see coming, the Data Box trade-off we almost got wrong, and what the whole thing cost at the end.
When I first sat down with the client — a 180-person professional services firm running a QNAP TS-h1290FX NAS with 15TB of active file share data — the IT manager's opening question was exactly what I expected: "Can we just drag and drop it?" The honest answer is no, and explaining why not without losing the room is one of the more diplomatically demanding parts of any NAS migration engagement. The technical reality is that a 15TB migration involving eight active SMB shares, Active Directory-joined users, NTFS ACLs with years of accumulated permission complexity, and a business that cannot tolerate more than a weekend of cutover disruption requires a structured approach with several non-obvious decision points along the way.
This post is the complete account of how we approached and executed that migration — what we decided, why we decided it, what went wrong, and what the final outcome looked like. I am sharing it because the public literature on NAS-to-Azure-Files migration is almost entirely documentation written from a feature perspective rather than a project perspective. What it does not cover is what you actually encounter when you run the process against a real business environment with legacy permissions, inconsistent share structures, and users who will ring the IT manager if their mapped drives are not back by Monday morning.
The environment — what we were working with
Before any migration planning, we spent two days on discovery and inventory. This is the step most organisations underestimate. Understanding the source environment in detail is not optional — every decision that follows depends on it.
| Share name | Size | File count | Last accessed | ACL complexity | Target tier |
|---|---|---|---|---|---|
| 1.4M files | Daily active | High — AD groups, nested permissions | Premium SSD | ||
| 2.8M files | Daily active | High — per-project folder ACLs | Premium SSD | ||
| 420K files | Daily active | Very high — sensitive, restricted | Premium SSD | ||
| 890K files | Daily active | Low — broad read access | Standard HDD | ||
| 3.2M files | Rarely — < once/quarter | Low — read-only post-migration | Cool Storage | ||
| 2.1M files | Rarely — < once/quarter | Low — read-only post-migration | Cool Storage | ||
| 12K files | Weekly | Low — broad access | Standard HDD | ||
| 8K files | Daily — automated | Low — service account only | Standard HDD |
The QNAP NAS was not domain-joined. It was using local QNAP users mapped to Active Directory accounts through a QNAP-specific LDAP bridge that the previous IT contractor had configured in 2021. The practical consequence: the file ACLs on the QNAP contained QNAP-local SIDs, not Active Directory SIDs. RoboCopy's /COPY:DATSO flag copies ACLs faithfully — but if those ACLs reference SIDs that do not exist in Active Directory, the migrated files will have broken permission entries that look correct in Explorer but deny access to users who should have it. This was the most significant complication of the entire project, and we discovered it during the inventory phase, not during the migration itself. Finding it early saved us from a permissions catastrophe on cutover weekend.
The three migration method decision — this is where most projects go wrong
Microsoft documents three primary paths for migrating NAS shares to Azure Files. Understanding which path is correct for a given environment is the most consequential decision in the entire project. Get it wrong and you are either rebuilding permissions manually or running a second migration to fix the first one.
| Method | Best for | Preserves ACLs | Downtime required | Speed | Our choice? |
|---|---|---|---|---|---|
| Azure Storage Mover | SMB/NFS shares, fully managed, no AFS needed long-term | ✓ Full fidelity | Minimal — continuous sync | Fast — FileREST API, tested to 100M items | Not chosen |
| Azure File Sync + RoboCopy | Hybrid deployments, cloud tiering, on-prem caching | ✓ Full fidelity via /COPY:DATSO | Minimal — sync then cutover | Moderate — depends on link bandwidth | ✓ Chosen |
| Azure Data Box + File Sync | >10TB, poor WAN bandwidth, offline transfer needed | ✓ Via RoboCopy to Data Box | Offline shipping window required | Very fast — no WAN dependency for bulk | Evaluated, not chosen |
We chose the Azure File Sync with RoboCopy path for three reasons specific to this environment. First, the client had a 500Mbps dedicated internet connection — sufficient to transfer 15TB within the project timeline without needing a physical Data Box device. Second, the business required a hybrid deployment post-migration — branch office users needed local caching of frequently accessed files without pulling everything from Azure over their WAN links. Azure File Sync provides exactly this through cloud tiering. Third, the SID mapping problem we discovered during inventory meant we needed to rebuild ACLs on a Windows Server before the migration anyway — Azure File Sync requires a Windows Server intermediate step, which gave us the right point to resolve the permission issue.
"The goal is to move the SMB file shares on your NAS appliance to a Windows Server, then utilize Azure File Sync for a hybrid cloud deployment. The migration needs to be done in a way that guarantees data integrity and availability — keeping downtime to a minimum."
— Microsoft Azure Files Migration DocumentationThe six-phase migration plan
The RoboCopy commands that actually worked
The RoboCopy flags matter more than most migration guides acknowledge. The wrong flags produce a copy that looks complete but is missing timestamps, attributes, or ACLs — and you only discover this after the QNAP is decommissioned and a user cannot access a file they could access last week.
Robocopy `
\\QNAP\Finance `
D:\SyncRoot\Finance `
/MT:32 /NP /NFL /NDL /B /MIR /IT `
/COPY:DATSO /DCOPY:DAT `
/UNILOG:C:\MigrationLogs\Finance_Phase3.log `
/TEE
# /TEE sends log output to both console and log file simultaneously # Run this as Administrator — /B mode requires elevated privileges # For QNAP shares requiring credentials: add /USER:domain\admin /PASS:xxxx
Robocopy `
\\QNAP\Finance `
D:\SyncRoot\Finance `
/MT:32 /NP /NFL /NDL /B /IT /XO `
/COPY:DATSO /DCOPY:DAT `
/UNILOG:C:\MigrationLogs\Finance_Delta_Phase5.log `
/TEE
# Review the log before Phase 6 — confirm error count is 0 or near 0
Robocopy `
\\QNAP\Finance `
D:\SyncRoot\Finance `
/MT:32 /NP /NFL /NDL /B /MIR /IT `
/COPY:DATSO /DCOPY:DAT `
/UNILOG:C:\MigrationLogs\Finance_Cutover.log `
/TEE
# Wait for File Sync to upload final changes to Azure Files # Monitor: Get-StorageSyncServerEndpoint | Select-Object SyncStatus # Only proceed with DFS-N redirect when SyncStatus = Healthy and # all pending file counts are zero
The four problems we actually hit
What it actually cost
| Component | Detail | Monthly cost |
|---|---|---|
| Azure Files Premium SSD | Finance + Projects + HR — 8.1TB provisioned at 0.21 GiB/month | $225 |
| Azure Files Standard HDD | Shared + Media + Backups — 3.1TB used at 0.04 GiB/month | $17 |
| Azure Files Cool tier | Archive2022 + Archive2023 — 3.8TB at 0.02 GiB/month | $11 |
| Storage Sync Service | Per-server registration fee — 1 registered server | $5 |
| Azure Private Endpoint | Private endpoint for storage accounts — avoids public internet traversal | $9 |
| Azure Backup for Files | Daily snapshots retained 30 days — replacing QNAP's backup function | $72 |
| Egress / transactions | Estimated based on observed usage in first month | $135 |
| Total estimated monthly Azure cost | $474 | |
The QNAP TS-h1290FX had a hardware replacement cycle of approximately 5 years. Annualised hardware cost: approximately $750/year. Add QNAP support contract ($225/year), on-site backup hardware ($300/year amortised), and IT time managing QNAP firmware updates and storage pool expansion: approximately $1,500/year total.
Azure Files at $474/month is $5,560/year — approximately 3.8x the on-premises cost. The client accepted this because the Azure Files cost includes global accessibility for remote workers, 99.99% SLA, no hardware replacement risk, and Azure Backup replacing a third-party backup appliance. The pure cost comparison is not the right frame for this decision.
The five things I would do differently
- I would use Azure Storage Mover for the archive shares. Archive2022 and Archive2023 were read-only after migration, needed no cloud tiering, and had low access frequency. Azure Storage Mover is faster than the File Sync path and does not require a Windows Server intermediate for these workloads. Using File Sync for the archive shares added unnecessary complexity without delivering any benefit that Storage Mover would not have provided.
- I would audit QNAP file naming conventions before starting the RoboCopy. The 23 files with illegal characters caused no catastrophic problems, but finding them during the sync phase rather than before the initial RoboCopy meant they were identified late. A simple PowerShell scan of the QNAP shares for characters that Azure Files does not permit would have flagged them in day one of the discovery phase and let us rename them at source before the first RoboCopy ran.
- I would have provisioned the Windows Server on Azure rather than on-premises. Using an on-premises Windows Server as the File Sync intermediate required the initial RoboCopy to run over the local network (fine) and the upload to run over the WAN (the bottleneck). Had we provisioned the Windows Server as an Azure VM in the same region as the storage accounts, we could have eliminated the WAN upload bottleneck entirely — the RoboCopy from local Windows Server to Azure VM would still use WAN, but subsequent File Sync activity between the VM and Azure Files would be intra-Azure at effectively unlimited speed.
- I would have estimated SID mapping time based on file count, not share count. The discovery phase gave us share sizes and file counts. We estimated SID mapping time based on the number of shares (8) rather than the number of files with non-standard ACLs. The Finance share alone had 1.4 million files, many with complex inherited permissions. File count, not share count, is the correct unit for estimating permission remediation work on a QNAP migration.
- I would have enabled Private Endpoints before registering the File Sync agent. We added Private Endpoints to the storage accounts after the File Sync agent was already configured and syncing. This required a brief sync pause and re-registration of the agent endpoint URLs. The correct sequence is to configure Private Endpoints and confirm connectivity before the File Sync agent is deployed. Azure Files should never traverse the public internet in a production migration — private endpoints should be a pre-requisite, not an afterthought.
- Discovery and inventory is not optional — budget two full days minimum. The SID problem, the illegal filename characters, and the QNAP authentication architecture were all discovered during inventory. Each would have been significantly more painful if discovered during the migration itself.
- Choose your migration method per share, not per project. Archive shares and active shares have completely different requirements. We should have used Storage Mover for archives and File Sync for active shares rather than a single method for all eight shares.
- The correct RoboCopy flags are /COPY:DATSO /DCOPY:DAT /B /MIR /IT. Any combination that omits Security (/S in DATSO) or uses Backup mode (/B) incorrectly will produce a copy that is missing ACLs or permission data. These are the flags that Microsoft recommends for full-fidelity migration — use them exactly as specified.
- Monitor the File Sync error log throughout the upload phase. Azure File Sync does not fail a sync job because of individual file errors — it logs them and continues. Files with illegal characters, path length violations, or permission problems are silently skipped. You must actively monitor the error log or you will discover missing files after cutover.
- DFS-N is the correct cutover mechanism — not DNS changes, not drive remapping. DFS Namespace redirect provides transparent cutover for all users without requiring any client-side changes. Users' mapped drives reconnect automatically. This is the correct approach for any SMB share migration where minimising user disruption is a requirement.
- Keep the QNAP live for two weeks after cutover — do not decommission immediately. Two weeks of parallel operation gives you a safe fallback if something is discovered post-cutover. The cost of keeping the QNAP powered on for two extra weeks is negligible. The cost of a failed cutover without a fallback is not.