MSP Tenant-to-Tenant Migration Checklist
A pre-migration checklist for MSPs moving a client's Microsoft 365 tenant: inventory, consent, throttling limits, and cutover verification steps.
What do I need to check before migrating a client’s Microsoft 365 tenant?
A safe client-tenant migration rests on five checks: a full inventory of mailboxes, OneDrive and SharePoint volume, consent and delegated-access setup, a Graph-throttling-aware run estimate, a pre-seed-then-cutover schedule, and a post-migration verification pass. Start this checklist at project scoping, not the week of cutover, since consent approval alone can take days.
Skipping the pre-flight on a client tenant migration rarely blows up during the migration itself. It blows up two weeks later, when a partner asks why their retention labels vanished, or a director asks why a Teams channel’s message history stops mid-2025. The fix at that point is expensive: re-running a partial migration against a tenant your client is already using day to day. A 30-minute checklist before you touch anything is cheaper than that conversation, every time. What breaks when you skip the pre-flight Most migration failures are not tooling failures — they are scoping failures. The migration tool did exactly what it was told; nobody told it about a data shape the source tenant actually had. The failure modes below account for the overwhelming majority of post-migration support tickets on client tenant moves. Consent granted for the wrong scope, discovered mid-run when a workload the client assumed was included silently has nothing to migrate A cutover window sized from a guess rather than the source tenant’s actual mailbox and OneDrive volume, blowing past the Graph throttling ceiling and the maintenance window both No agreed conflict-resolution rule, so items already at the destination get silently duplicated or silently skipped depending on which tool default happened to apply No evidence kept of what ran, so a client complaint six weeks later has no baseline to check against Step 1 — Inventory the source tenant Before you request any consent, get a real count of what the source tenant holds. This is the number that drives your throttling estimate in Step 3 and your cutover-window size in Step 4 — skip it and every later step is a guess. Mailbox count and total mailbox size, including shared mailboxes and any legal-hold mailboxes that need different handling OneDrive volume per user — total GB and file count, since large media libraries change the throughput math more than user count does SharePoint sites and document libraries, with an eye on any site collection with unusually deep folder nesting Teams and channel message history depth, including which channels carry private-channel chat (a workload with its own documented caveats) Planner boards and Bookings calendars in active use Retention labels currently applied, and which libraries or mailboxes they cover Step 2 — Settle consent and delegated access Pick the access model before you request anything from the client, because each one has a different approval path and a different lead time. The options are GDAP delegated admin, admin consent granted through your own Azure app registration, client-provided app credentials, or direct global-admin consent from someone at the client with the authority to grant it. None of these requires a CSP relationship — a one-off migration does not need to become a standing partnership. Whichever you pick, confirm the consent covers both the source and the destination tenant before you schedule anything, since a migration needs write access on both sides. Step 3 — Size the run against Graph throttling Microsoft Graph enforces a documented ceiling of roughly 400 requests per 10 seconds per app per tenant, and that ceiling applies independently on the source tenant and the target tenant — the slower of the two sets your real throughput. Destination ingestion quotas add a second cap on top of that, so a source-side inventory that looks fast can still be bottlenecked by how quickly the target tenant accepts writes. Use your Step 1 inventory to estimate a realistic run duration rather than assuming a flat transfer rate. As a real throughput reference: one production migration moved 153,584 files totalling 178 GB in 36 hours with zero errors, in April 2026 — useful as a sanity check on your own estimate, not a promise of identical speed for every tenant shape. Step 4 — Pre-seed, then cut over Run the bulk of the transfer as a pre-seed pass well before the cutover window, then run a short delta pass during the actual cutover to pick up what changed since the pre-seed. This keeps the client-facing downtime window small, since the delta pass only has to move recent changes rather than the whole tenant. Items already present at the destination are detected by content hash and skipped, so a re-run after an interruption does not duplicate content Conflict-merge rules are configurable per workload, but never applied silently — decide the rule with the client before the run, not during it Schedule the delta pass for the shortest realistic downtime window your Step 3 estimate supports Step 5 — Verify before you hand the tenant back The migration is not done when the transfer finishes — it is done when you can prove to the client what moved. Keep the evidence from this step; it is what answers the support ticket that comes in three weeks later asking whether something specific actually migrated. Mailbox and OneDrive item counts at the destination, compared against the Step 1 source inventory Spot-check a sample of Teams channels for message history continuity, including any private channels flagged in Step 1 Confirm retention labels landed on the destination libraries they were applied to at the source Export a run log showing what ran, when, and with zero unresolved conflicts — or a documented resolution for any that occurred What this checklist does not cover This checklist covers Microsoft 365 to Microsoft 365 migrations only — cross-platform moves involving Google Workspace, Slack, or Box are out of scope, and BitTitan, ShareGate, or Quest are better fits there. Teams private-channel chat history, retention-label propagation across libraries, and per-user OneDrive sharing-link rewrites all carry documented caveats worth reading before you promise a client full fidelity on any of them. Restoring or re-applying content from an export is a manual operator step — there is no one-click tenant rollback if a cutover needs to be undone.
The MSP pre-flight checklist for a Microsoft 365 tenant-to-tenant migration
Inventory the source tenant
Before you request any consent, get a real count of what the source tenant holds. This is the number that drives your throttling estimate in Step 3 and your cutover-window size in Step 4 — skip it and every later step is a guess. Mailbox count and total mailbox size, including shared mailboxes and any legal-hold mailboxes that need different handling OneDrive volume per user — total GB and file count, since large media libraries change the throughput math more than user count does SharePoint sites and document libraries, with an eye on any site collection with unusually deep folder nesting Teams and channel message history depth, including which channels carry private-channel chat (a workload with its own documented caveats) Planner boards and Bookings calendars in active use Retention labels currently applied, and which libraries or mailboxes they cover
Settle consent and delegated access
Pick the access model before you request anything from the client, because each one has a different approval path and a different lead time. The options are GDAP delegated admin, admin consent granted through your own Azure app registration, client-provided app credentials, or direct global-admin consent from someone at the client with the authority to grant it. None of these requires a CSP relationship — a one-off migration does not need to become a standing partnership. Whichever you pick, confirm the consent covers both the source and the destination tenant before you schedule anything, since a migration needs write access on both sides.
Size the run against Graph throttling
Microsoft Graph enforces a documented ceiling of roughly 400 requests per 10 seconds per app per tenant, and that ceiling applies independently on the source tenant and the target tenant — the slower of the two sets your real throughput. Destination ingestion quotas add a second cap on top of that, so a source-side inventory that looks fast can still be bottlenecked by how quickly the target tenant accepts writes. Use your Step 1 inventory to estimate a realistic run duration rather than assuming a flat transfer rate. As a real throughput reference: one production migration moved 153,584 files totalling 178 GB in 36 hours with zero errors, in April 2026 — useful as a sanity check on your own estimate, not a promise of identical speed for every tenant shape.
Pre-seed, then cut over
Run the bulk of the transfer as a pre-seed pass well before the cutover window, then run a short delta pass during the actual cutover to pick up what changed since the pre-seed. This keeps the client-facing downtime window small, since the delta pass only has to move recent changes rather than the whole tenant. Items already present at the destination are detected by content hash and skipped, so a re-run after an interruption does not duplicate content Conflict-merge rules are configurable per workload, but never applied silently — decide the rule with the client before the run, not during it Schedule the delta pass for the shortest realistic downtime window your Step 3 estimate supports
Verify before you hand the tenant back
The migration is not done when the transfer finishes — it is done when you can prove to the client what moved. Keep the evidence from this step; it is what answers the support ticket that comes in three weeks later asking whether something specific actually migrated. Mailbox and OneDrive item counts at the destination, compared against the Step 1 source inventory Spot-check a sample of Teams channels for message history continuity, including any private channels flagged in Step 1 Confirm retention labels landed on the destination libraries they were applied to at the source Export a run log showing what ran, when, and with zero unresolved conflicts — or a documented resolution for any that occurred
Frequently asked questions
How long before cutover should I start the pre-flight checklist?
Start the inventory pass as soon as the project is scoped, well before you book a cutover window. Consent and delegated-access setup can take a client days to approve, and a Graph-throttling-aware run estimate needs the inventory numbers first. Doing this the week of cutover is the most common source of slipped dates.
Do I need to be a CSP partner to run this migration?
No. The checklist works with GDAP delegated admin, admin consent through your own Azure app registration, client-provided app credentials, or direct global-admin consent. No CSP relationship is required for any of these paths, so a one-off client migration does not force you into a partnership you do not want.
What happens if the migration is interrupted partway through?
Items already present at the destination are detected by content hash and skipped on the next run, so a resumed migration does not re-copy what already landed. Conflict-merge rules are configurable, but they are never applied silently — you choose how collisions are resolved before the run continues.
Related topics
- tenant-to-tenant migration
- msp migration checklist
- gdap delegated access
- microsoft graph throttling
- migration cutover verification