Microsoft has a built-in migration path from Google Workspace to Exchange Online. It moves mail, calendars, and contacts without a third-party tool, and for most small businesses it's the right choice. It's also unforgiving about prerequisites: skip one and the batch fails with errors that don't point at the real cause.
This runbook walks through the moving parts in the order that works, and the things people forget until users start asking where their stuff went.
What moves and what doesn't
| Data | Built-in migration | Notes |
|---|---|---|
| Gmail mail and labels | Yes | Labels become folders. Mail with several labels is copied into each folder. |
| Google Calendar | Yes | Recurring meetings come across, but check shared and resource calendars by hand. |
| Contacts | Yes | Personal contacts only. Shared or directory contacts need separate handling. |
| Google Drive | No | Use SharePoint Migration Manager, a separate project. |
| Filters, signatures, delegation | No | Users recreate these, or you script them afterward. |
| Google Groups | No | Rebuild as Microsoft 365 groups, distribution lists, or shared mailboxes. |
Prerequisites
Get every one of these done before you create a batch:
- Microsoft 365 tenant with your domain verified, and licensed users created with the same addresses they have in Google.
- A Google Cloud project and service account with domain-wide delegation, and the Gmail, Calendar, Contacts, and People APIs enabled. Microsoft's migration uses this to read each mailbox.
- Mail routing subdomains. The built-in migration relies on subdomains so mail can reach users on both platforms during the transition. You add a routing subdomain for Microsoft 365 and one for Google, with matching forwarding and address settings. This is the step most often misconfigured.
- Admin accounts on both sides that aren't tied to someone who's leaving.
- Lowered DNS TTLs on your MX and autodiscover records, several days ahead.
The migration batch
In the Exchange admin center, under Migration, you create a Google Workspace migration batch:
- Migration endpoint: uses the service account's JSON key.
- Users: a CSV of the users in this batch.
- Target delivery domain: the Microsoft 365 routing subdomain from the prerequisites.
Start with a pilot batch of two or three users who will tell you honestly what's missing. Once the pilot is clean, run the rest in batches sized so each one finishes overnight.
You can monitor progress from Exchange Online PowerShell:
Connect-ExchangeOnline
Get-MigrationBatch | Format-Table Identity, Status, TotalCount, SyncedCount, FailedCount
Get-MigrationUser -BatchId "Pilot" | Get-MigrationUserStatistics |
Format-Table Identity, Status, ItemsSynced, ItemsSkipped, ErrorCutover
When batches have finished their initial sync and are keeping up with incremental syncs:
- Switch MX to Microsoft 365 at a quiet time.
- Let the batches run a final incremental sync to catch mail that arrived in Gmail during DNS propagation.
- Complete the batches.
- Update SPF, and publish DKIM and DMARC for Microsoft 365. Don't leave Google's
include:in SPF any longer than you need it. - Set up Outlook and phones for users. This is the step that fills the help desk queue, so have instructions ready before cutover.
Common failures
- Batch fails immediately: usually the service account's domain-wide delegation scopes, or an API that wasn't enabled.
- Some users fail, others succeed: check that the user exists in Microsoft 365 with a license and a matching primary address.
- Mail during migration disappears: almost always routing. Look at the forwarding and routing subdomain setup first.
- Calendar invites look wrong after cutover: meetings organized by users who haven't migrated yet stay tied to Google until those users move.