Someone asks you how long the migration will take. You have one document library, you know it is 200 GB, and the cutover has to fit in a weekend.
So you go looking for a number. Every vendor page says the same thing. It depends on your environment. Plan carefully. Follow best practices. Twenty minutes later you still have nothing you could put in an email to the people who have to stop working while it runs.
Microsoft does publish numbers. They sit in a performance guide that vendor comparison posts almost never quote, probably because the numbers are unflattering to everyone.
The size of your library is also a weak predictor of how long it takes. Two libraries of exactly 200 GB can be four hours apart. Add version history and one of them turns into a two day job. Sizing a migration in gigabytes is the mistake, and it is the reason so many cutover windows get blown.
The numbers Microsoft actually publishes
From the migration performance guide for SharePoint and OneDrive (ms.date 2025-09-16), here is what the service is expected to sustain, by the kind of content you are moving:
| Content type | Examples Microsoft gives | Ceiling |
|---|---|---|
| Light | ISO files, video files | 10 TB/day |
| Medium | List items, Office files around 1.5 MB | 1 TB/day |
| Heavy | List items with custom columns, small files around 50 kb | 250 GB/day |
The middle row is the one that applies to you. Ordinary Office documents, the thing most document libraries are actually full of, sit at 1 TB/day. That is roughly 42 GB an hour if the run is perfectly steady, which it will not be.
Two rules sit underneath the table, and Microsoft states both plainly. Large files migrate faster than small ones, because small files carry proportionally more overhead. And files migrate faster than list items. Between them, those two rules explain why the same 200 GB behaves so differently from one library to the next.
Why two 200 GB libraries are not the same job
Take the library apart by average file size instead of total size.
Library A holds 200 GB of ordinary Office documents. At roughly 1.5 MB each, that is about 136,000 files. Medium tier, 1 TB/day, so the transfer is around five hours.
Library B holds 200 GB of scanned documents at about 50 kb each. That is roughly four million files. Heavy tier, 250 GB/day, so the same 200 GB takes closer to nineteen hours.
Same size on the storage report, nearly four times the wall clock, and nobody who sized that job in gigabytes saw it coming.
So find the average file size before you plan around either number. Total size divided by item count gets you there in one calculation, and it tells you which row of the table you are on.
Both numbers are easier to get than people expect. Library settings on the source shows the item count. Storage metrics on the site shows the size, broken down per library, and it counts every version rather than only the current one. If you are coming off a file share instead, Get-ChildItem with Measure-Object gives you the same two numbers in one line.
Run SPMT in scan mode first, whichever source you are on. The setting is Only perform scanning, and Microsoft describes it as a preassessment. It walks the source without moving anything, so you get the real file count and the real problem list before you have committed a weekend to the answer. A scan that takes an hour on Tuesday is worth more than a migration that fails at 2am on Sunday.
Version history is the thing that ruins the estimate
Your 200 GB figure is almost certainly the current version of every file. It is what the site storage report shows you. But a library with versioning switched on has been keeping every draft anyone saved, and SharePoint in Microsoft 365 will hold 50,000 major versions per item before it stops.
If the average file in that library has ten versions, the migration is not moving 200 GB. It is moving something closer to 2 TB. At the medium tier that is two days, not five hours, and you found out on Saturday night.
That is one setting, and Microsoft documents it precisely. In the SPMT settings (ms.date 2026-08-18), under Filters:
Migrate file version history. If set to Off, only the most recent version of the file is migrated. If set to On, you can choose whether to keep all versions, or limit it to a specific number.
Which gives you three positions, not two:
- Off. Current version only. Fastest possible run, and you lose the history.
- On, keep all versions. Everything comes across. Budget for the multiplier.
- On, limited to a number. The setting is called Number of versions to migrate. This is the one most people should pick and almost nobody knows exists.
Five versions is a defensible middle. It satisfies the person who says “we might need to roll something back” without moving a decade of autosaves. If you have a retention obligation that genuinely requires full history, keep all versions, but then size the job on the real payload and stop pretending the weekend is enough.
Work out your multiplier before you schedule anything. If you cannot get a version count out of the source, assume the history is bigger than you think, because it usually is.
Permissions migrate. Identities are what break.
The question people actually mean when they ask whether permissions survive is whether the right people can still open the files on Monday.
Permissions do migrate. The setting is Preserve SharePoint permissions, and there are matching settings for permissions inheritance and for file share permissions. My earlier post on SPMT limits goes through the vendor claims that say otherwise and why they are out of date.
The part that breaks is the identity behind each permission. A permission on the source points at an account. That account has to resolve to something in Microsoft Entra ID on the destination, and nothing guarantees that it will.
SPMT tries automatically. From the same settings page:
Automatic user mapping. By default, this setting is set to On. On-premises users are automatically mapped to Microsoft Entra ID users where possible.
“Where possible” is carrying real weight there. Any account it cannot match is an account whose permissions do not land. Leavers, service accounts, a contractor whose on-premises login never existed in the cloud, anyone renamed after a marriage or a rebrand: all of those are misses.
For anything you cannot leave to chance, you supply a mapping file. It is a CSV with no header row and three required columns (ms.date 2025-04-07):
- Column A: the source login name. SharePoint Server 2013 and later also accept a SID.
- Column B: the user principal name on the target.
- Column C: TRUE if the target is an AD group, FALSE if it is not.
There is a trap in how the two settings interact, and Microsoft spells it out:
If you choose to use a custom user mapping file and want to preserve user permissions, turn off Automatic user mapping. By doing so, if a user isn’t found in the mapping file, the tool doesn’t look it up in Microsoft Entra ID.
Leave automatic mapping on alongside your file and the tool will still go hunting in Entra for anyone your file missed. That sounds helpful and is the opposite. It means a wrong match can be made silently, and you will not know which permissions were guessed.
The limits that stop a file dead
Throughput decides how long. A separate set of limits decides whether a file arrives at all. These are worth a glance before you start, and I have written them up properly in the SPMT limits post, so here they are in short (ms.date 2025-05-29):
| Limit | Value |
|---|---|
| File upload | 250 GB per file |
| Whole decoded path, including file name | 400 characters |
| Files and folders in one library | 30 million |
| Versions | 50,000 major versions, 511 minor |
Path length is the one that eats files in a document library migration without announcing itself. It is not the file name. It is the folder path plus the name, decoded, and a deep folder structure on a long site URL can cross it while everything still looks tidy on screen. Files that cross it do not arrive.
Two practical numbers from the same set. Microsoft asks for a minimum of 150 GB of free space in the SPMT working folder on your own machine, which is where the packaging happens. And if you are moving more than 100 TB, Microsoft asks you to open a support request before you start.
What this does not fix
The ceilings in the table are what the service will sustain. They are not what you will get.
I have not put a stopwatch on a 200 GB library and neither has the table. These are Microsoft’s published maxima, and the arithmetic above is a planning estimate built on them. Treat it as the number you defend a schedule with, not a guarantee you make to a client.
Something else will pull you below the ceiling, and it is usually one of these.
Throttling. Microsoft applies tighter limits to background applications, migration included, during weekday daytime hours, and says the service is ready for higher volume in the evenings and at weekends. Throttling rules cannot be disabled or suspended, and opening a support ticket does not lift them. Schedule accordingly.
Your source, not the cloud. Microsoft’s own telemetry points at source reading as the typical bottleneck. Disk speed on the source, disk speed on the migration machine, RAM, antivirus competing for the same disk. A slow file server will hold you well under 1 TB/day no matter how clean the destination is.
How you package the work. The guidance asks for at least 250 files per transfer and packages between 100 MB and 250 MB, and warns against having more than 5,000 migration jobs sitting in the queue at once. Over-queuing loads the database and slows the whole thing down.
One more thing that is not a migration problem but arrives looking like one. Microsoft recommends syncing no more than 300,000 files in a single library. Land a library above that and the migration report will say success while users tell you sync is broken all week.
The bottom line
Stop sizing the job in gigabytes. Divide total size by item count to find which throughput tier you are on, then multiply by your average version count to get the real payload. That number, against 1 TB/day for ordinary documents, is your estimate.
Then decide the version history setting deliberately, before the run rather than during it. It is the one control that changes the answer by an order of magnitude, and it is sitting in the settings panel with a default that nobody chose.