Converting hybrid users to cloud-only
More and more organizations are stepping away from syncing on-prem Active Directory to Entra ID and moving to a cloud-only identity model. Reasons vary - reducing on-prem footprint, retiring domain controllers, simplifying lifecycle management, or just not needing AD anymore after moving everything to SaaS.
The tricky part is converting existing synced users to cloud-only without losing their data, licenses, or group memberships. Here's the process I use.
The process
1. Move the user to a non-synced OU
In your on-prem AD, move the user's account to an OU that's excluded from the Entra Connect sync scope. This is what disconnects them on the on-prem side - Entra Connect will see them as out of scope on the next cycle.
2. Force a delta sync
On your Entra Connect server:
Start-ADSyncSyncCycle -PolicyType Delta
3. The user is deleted from Entra
After the sync runs, Entra Connect notices the user is no longer in scope and deletes them from Entra ID. Don't panic - they're not gone, just soft-deleted. Deleted users sit in the recycle bin for 30 days.
4. Restore the user from Deleted Users
Entra admin center → Users → Deleted users → select the user → Restore user.
Or via PowerShell:
Connect-MgGraph -Scopes "User.ReadWrite.All"
Restore-MgDirectoryDeletedItem -DirectoryObjectId <objectId>
At this point the user is back, but they're still tagged as synced (OnPremisesSyncEnabled = True) and still carry the old OnPremisesImmutableId pointing at the on-prem object. That's what step 5 fixes.
5. Clear the ImmutableId
This is where my script comes in: Convert-ToCloudOnlyUser.ps1 Download. It uses a direct Microsoft Graph PATCH to set OnPremisesImmutableId to null, which finally breaks the sync anchor and flips the user to cloud-only.
# Single user
.\Convert-ToCloudOnlyUser.ps1 -UserPrincipalName "jane.doe@contoso.com"
# Multiple users in one run, skip the per-user confirmation
.\Convert-ToCloudOnlyUser.ps1 `
-UserPrincipalName "user1@contoso.com","user2@contoso.com","user3@contoso.com" `
-Force
Example output:
Checking for Microsoft Graph PowerShell SDK...
Microsoft Graph module is already installed.
Connecting to Microsoft Graph...
Successfully connected to Microsoft Graph.
----------------------------------------
Retrieving user information for: jane.doe@contoso.com
----------------------------------------
User Details:
Display Name : Jane Doe
User Principal Name : jane.doe@contoso.com
Account Enabled : True
OnPremisesSyncEnabled: True
OnPremisesImmutableId: xJ5m0KQfHEqgR7vQ2nYp3Q==
Clearing ImmutableId via Graph API PATCH...
Successfully cleared ImmutableId for Jane Doe.
Verifying result...
OnPremisesSyncEnabled: False
OnPremisesImmutableId: (null)
Jane Doe is now a cloud-only user.
The script accepts an array of UPNs, authenticates once, and processes them sequentially - good for batch runs of 10-50 users.
Caveats - please read before running this on everyone
This is a one-way door. Reverting is painful and data-losing. A few things to verify before you start:
- External systems provisioned from Entra. HR platforms, SCIM-provisioned SaaS apps, ServiceNow, door access systems, bespoke Graph integrations - when the user disappears from Entra in step 3, many of these will see a "user left" event and delete the user on their side. When the user comes back as cloud-only and reprovisions downstream, the account is recreated - but any per-user configuration inside that system often isn't. A door access system is the classic example: the user reappears, but their card permissions and zone assignments are gone. Same pattern applies to individually-granted roles in line-of-business apps, custom attributes in HR tools, and anything configured manually against a specific user record.
- MFA methods and Conditional Access. These stick to the ObjectId, so they usually survive - but verify on your pilot batch.
- Mailbox moves in flight. Don't convert users in the middle of a cross-tenant or hybrid mailbox migration.
- Licensing. Group-based licensing should re-apply automatically; direct assignments generally survive. Spot-check after the conversion.
- Always pilot. Run this on 2-3 users first. Verify email, Teams, OneDrive, Intune enrollment, SSO, and your key business apps still work. Only then scale up.
What about groups?
Users are only half the job. If your on-prem AD also syncs groups (security groups, distribution lists, mail-enabled security groups), those all carry the same OnPremisesSyncEnabled = True flag and have to be dealt with before you shut off sync.
Unfortunately, groups are harder than users: there's no equivalent to clearing the ImmutableId for a group. You can't convert one in place. The practical path is recreate-and-re-point:
- For each synced group, create a new cloud-only group in Entra with the same name and members.
- Update every place that references the old group by ObjectId: Conditional Access policies, Intune device/user targeting, license assignment, app role assignments, SharePoint permissions, mailbox delegation, Teams, etc.
- Delete the old synced group once nothing references it.
A minimal PowerShell skeleton for step 1:
Connect-MgGraph -Scopes "Group.ReadWrite.All", "GroupMember.ReadWrite.All"
$oldGroup = Get-MgGroup -Filter "displayName eq 'Finance-ReadOnly'"
$members = Get-MgGroupMember -GroupId $oldGroup.Id -All
$newGroup = New-MgGroup `
-DisplayName $oldGroup.DisplayName `
-Description $oldGroup.Description `
-MailEnabled:$False `
-SecurityEnabled `
-MailNickName (($oldGroup.DisplayName -replace '\s','').ToLower())
foreach ($m in $members) {
Add-MgGroupMember -GroupId $newGroup.Id -DirectoryObjectId $m.Id
}
A few things to watch out for:
- Nested groups. Do leaf groups first, then groups that contain other groups. Otherwise the member copy won't resolve the nested group correctly during the rebuild.
- Mail-enabled distribution lists. For eligible DLs, use Exchange Online's Upgrade distribution list to Microsoft 365 Groups option. You get a cloud group plus modern collaboration features in one step.
- Dynamic groups. If a synced group was used for license assignment or Intune targeting, consider replacing it with an Entra dynamic group based on user attributes. Less to maintain, and it auto-updates as people change roles.
- Group-based licensing. Users lose their license the moment you remove them from the old synced group. Add them to the new cloud group first, verify the license lands, then delete the old group.
- ObjectId references. Anything that references the old group by GUID (custom Graph apps, ARM RBAC, third-party SaaS role mappings) will break on rebuild. Inventory these before you start.
- Budget time. This is where a hybrid-to-cloud migration gets genuinely labor-intensive. Script what you can, but each group tends to need a human eyeball on its dependencies.
Finally: disable tenant sync
Once every user and group has been converted and nothing else still depends on sync, flip the tenant-level OnPremisesSyncEnabled flag off so Entra stops treating the tenant as a hybrid identity tenant. You can do this with Microsoft Graph PowerShell.
Install or update the module if you haven't already:
Install-Module Microsoft.Graph -Force
Connect with write permission on the organization:
Connect-MgGraph -Scopes "Organization.ReadWrite.All"
Check the current state - True means sync is on:
Get-MgOrganization | Select-Object DisplayName, OnPremisesSyncEnabled
DisplayName OnPremisesSyncEnabled
----------- ---------------------
Contoso True
Disable sync. onPremisesSyncEnabled isn't exposed as a direct switch parameter, so pass it through -BodyParameter:
$orgId = (Get-MgOrganization).Id
$params = @{
onPremisesSyncEnabled = $false
}
Update-MgOrganization -OrganizationId $orgId -BodyParameter $params
Important warnings:
- Microsoft can take up to 72 hours to complete deactivation across the tenant. The time depends on the number of objects in your subscription.
- You cannot cancel this action once it's submitted. It has to complete before you can take any other directory-sync action, including re-enabling sync.
- If you do re-enable later, you'll trigger a full sync of all objects, which can take a considerable time.
Verify the result - OnPremisesSyncEnabled should now be empty (null):
Get-MgOrganization | Select-Object DisplayName, OnPremisesSyncEnabled
DisplayName OnPremisesSyncEnabled
----------- ---------------------
Contoso
Once that returns null, you can uninstall Entra Connect and decommission the sync server.
For a screenshot-led walkthrough of the same procedure, Ali Tajran's guide Disable Active Directory synchronization is a good companion reference.
That's the whole flow: convert users, then convert groups, then flip the tenant flag. Take it slow, pilot on a handful of users first, and make sure every downstream system is ready for the switch.