Table of Contents
Remove Service Plan PowerShell to Manage User Functionality
Note: This post is now obsolete. Please see this article for an updated approach to the problem.
Service plans are non-saleable elements of a Microsoft licensable product (SKU or stock keeping unit). SKUs are what people often think of when they discuss licenses. Individual Microsoft 365 accounts can have multiple SKUs, such as TOPIC_EXPERIENCES, ENTERPRISEPACK, and EMSPREMIUM. The product names for these SKUs are Viva Topics, Office 365 E3, and Enterprise Mobility and Security E5. Product names appear in places like the Billing section of the Microsoft 365 admin center (Figure 1).

At a more granular level, a “bundled” SKU like Office 365 E3 includes multiple service plans, each of which enable access to some functionality like an app. This page lays details the connections between SKUS and service plans.
At the time of writing, Office 365 E3 covers 28 service plans and Office 365 E5 has 53. Office 365 E5 includes service plans to license capabilities like advanced compliance features, customer lockbox, advanced auditing, content explorer, server-based auto-labeling for sensitivity labels and retention labels, records management, and information barriers.
Microsoft introduces new service plans to enhance its ability to license new features to different user communities or to provide control over user access to a new feature. Teams is a good example. The Teams service plan (TEAMS1) is in many Office 365 and Microsoft 365 SKUs. In April, Microsoft announced they would add the Teams Pro service plan to some SKUs and will use the Teams Pro service plan to allow accounts licensed with those SKUs to access new features. To date, Microsoft has not added the Teams Pro service plan to any SKU in my tenant nor have they described what features the new service plan will cover.
Reviewing Available Service Plans
In some cases, tenant administrators might not want users to be able to access a licensed app or capability. Perhaps the feature is obsolete, or the organization has different software to do the same thing, or maybe a delay is necessary to enable preparation of training, documentation, and support. Some years ago, Microsoft made a big thing about Kaizala and its impending integration into Teams. Kaizala is now an obsolete feature that’s still available in Office 365 E3 and E5. Sway is in the same category. Microsoft Bookings is an optional feature which isn’t often used by enterprise users, but it’s also part of Office 365 E3 and E5. In short, when you review the set of service plans bundled into Office 365 and Microsoft 365 SKUs, you might be surprised at the amount of unwanted debris in the mix.
Removing Individual Service Plans
Let’s say that we want to remove individual service plans from SKUs assigned to users. This post describes how to report the accounts assigned individual service plans (licenses) and explains how Azure AD stores the service plan information in user accounts. We want to go further by removing access to selected service plans, and as it turns out, we must use cmdlets from the older Microsoft Online Services module to get the job done. It’s possible to use the Set-AzureADUserLicense cmdlet to remove a service plan from an account. Laziness and the availability of some existing code to do the job stopped me using this cmdlet.
In any case, I wrote a script to demonstrate the principle of the steps to remove an individual service plan from multiple Microsoft 365 accounts. Three versions are available.
- Using Microsoft Online Services cmdlets to remove service plans (download the full script from GitHub).
- Using Azure AD cmdlets (download the Azure AD version from GitHub).
- Using Microsoft Graph PowerShell SDK cmdlets (download the Graph SDK version from GitHub).
Given that Microsoft deprecated the licensing management cmdlets in the MSOL and Azure AD modules in 2023, it makes sense to focus on the version based on the Microsoft Graph PowerShell SDK.
The major steps to remove a service plan from Azure AD licenses with PowerShell are:
- Determine the set of SKUs (products) available in the tenant.
- Select the SKU to remove a service plan from. A tenant might use many SKUs, so we read the information with Get-AzureADSubscribedSKU (or Get-MgSubscribedSku) and ask the administrator to choose a SKU.
- Select the service plan from the chosen SKU to remove. This is a matter of reading the service plans from the SKU and asking the administrator to choose one.
- Select the target accounts. I use Get-ExoMailbox to fetch a set of user mailboxes because this cmdlet supports a wide range of server-side filters (for instance, everyone in a country or department). The important thing is that you fetch the Azure AD object identifiers for the target accounts. The Microsoft Graph PowerShell SDK version doesn’t use Exchange Online because it reads the licensed account information direct from Azure AD.
- Access each account (using its object identifier) and remove the service plan. The MSOL version does this by running the Set-MsolUserLicense cmdlet. The Azure AD version uses the Set-AzureADUserLicense cmdlet, while the Graph SDK uses Set-MgUserLicense.
- Report the service plans removed from SKUs assigned to the target mailboxes.
Figure 2 shows the MSOL version of the script in action. You can see the selection of the service domain, SKU, and service plan and processing of user accounts. In this case, the selected options remove the Sway service plan from the ENTERPRISEPACK (Office 365 E3) SKU.

The report output is a CSV file. Figure 3 shows the information captured in the report as viewed through the Out-GridView cmdlet.

PowerShell Scores Again
I’m sure others will have different ways to solve the problem of removing service plans from SKUs, which is just fine. What’s obvious here (once again) is that PowerShell is a very flexible tool for automating administrative operations. Which is why I am so surprised when tenant administrators admit that they have never taken the time to become acquainted with the basics of PowerShell scripting. It’s not difficult; there are tons of available examples to learn from; and it gets work done. All good stuff!
Learn more about how Office 365 really works on an ongoing basis by subscribing to the Office 365 for IT Pros eBook. Our monthly updates keep subscribers informed about what’s important across the Office 365 ecosystem.
Every time I run your script – it returns ‘Total of 0 matching mailboxes found’ regardless of license or feature SKU selected.
Well, can you share the output of the Get-MgSubscribedSKU cmdlet from your tenant, and the SKU/service plan you’re trying to remove?
I took a look at the script and made some improvements. Grab a new copy from GitHub and see what you think.
Every time I run your script – it returns ‘Total of 0 matching mailboxes found’ regardless of license or feature SKU selected. -> Same on my end. Output:
Get-MgSubscribedSKU
Id AccountId AccountName AppliesTo CapabilityStatus ConsumedUnits SkuId SkuPartNumber SubscriptionIds
— ——— ———– ——— —————- ————- —– ————- —————
47e211f4-33e3-42a4-b4a7-7eefea1ecc6f_4a51bf65-409c-4a91-b845-1121b571cc9d 47e211f4-33e3-42a4-b4a7-7eefea1ecc6f phoenixtestlab User Enabled 0 4a51bf65-409c-4a91-b845-1121b571cc9d FLOW_PER_USER {8a71a968-c1d8-47…
47e211f4-33e3-42a4-b4a7-7eefea1ecc6f_6470687e-a428-4b7a-bef2-8a291ad947c9 47e211f4-33e3-42a4-b4a7-7eefea1ecc6f phoenixtestlab Company Enabled 0 6470687e-a428-4b7a-bef2-8a291ad947c9 WINDOWS_STORE {6a078885-5519-47…
47e211f4-33e3-42a4-b4a7-7eefea1ecc6f_bf666882-9c9b-4b2e-aa2f-4789b0a52ba2 47e211f4-33e3-42a4-b4a7-7eefea1ecc6f phoenixtestlab User Enabled 1 bf666882-9c9b-4b2e-aa2f-4789b0a52ba2 POWERAPPS_PER_APP_IW {f4ccac71-3078-47…
47e211f4-33e3-42a4-b4a7-7eefea1ecc6f_f30db892-07e9-47e9-837c-80727f46fd3d 47e211f4-33e3-42a4-b4a7-7eefea1ecc6f phoenixtestlab User Enabled 14 f30db892-07e9-47e9-837c-80727f46fd3d FLOW_FREE {04208c17-f520-4f…
47e211f4-33e3-42a4-b4a7-7eefea1ecc6f_726a0894-2c77-4d65-99da-9775ef05aad1 47e211f4-33e3-42a4-b4a7-7eefea1ecc6f phoenixtestlab User Enabled 0 726a0894-2c77-4d65-99da-9775ef05aad1 MICROSOFT_BUSINESS_CENTER {576bd289-efe4-4e…
47e211f4-33e3-42a4-b4a7-7eefea1ecc6f_606b54a9-78d8-4298-ad8b-df6ef4481c80 47e211f4-33e3-42a4-b4a7-7eefea1ecc6f phoenixtestlab User Enabled 1 606b54a9-78d8-4298-ad8b-df6ef4481c80 CCIBOTS_PRIVPREV_VIRAL {01c9d9be-66af-4b…
47e211f4-33e3-42a4-b4a7-7eefea1ecc6f_dcb1a3ae-b33f-4487-846a-a640262fadf4 47e211f4-33e3-42a4-b4a7-7eefea1ecc6f phoenixtestlab User Enabled 6 dcb1a3ae-b33f-4487-846a-a640262fadf4 POWERAPPS_VIRAL {472960bb-b402-40…
47e211f4-33e3-42a4-b4a7-7eefea1ecc6f_e0dfc8b9-9531-4ec8-94b4-9fec23b05fc8 47e211f4-33e3-42a4-b4a7-7eefea1ecc6f phoenixtestlab User Enabled 1 e0dfc8b9-9531-4ec8-94b4-9fec23b05fc8 Microsoft_Teams_Exploratory_Dept {75caabf1-cdb2-48…
47e211f4-33e3-42a4-b4a7-7eefea1ecc6f_a403ebcc-fae0-4ca2-8c8c-7a907fd6c235 47e211f4-33e3-42a4-b4a7-7eefea1ecc6f phoenixtestlab User Enabled 13 a403ebcc-fae0-4ca2-8c8c-7a907fd6c235 POWER_BI_STANDARD {1e1fc1ee-94c9-4f…
47e211f4-33e3-42a4-b4a7-7eefea1ecc6f_06ebc4ee-1bb5-47dd-8120-11324bc54e06 47e211f4-33e3-42a4-b4a7-7eefea1ecc6f phoenixtestlab User Enabled 5 06ebc4ee-1bb5-47dd-8120-11324bc54e06 SPE_E5 {bb6b2f4e-599c-4b…
47e211f4-33e3-42a4-b4a7-7eefea1ecc6f_05e9a617-0261-4cee-bb44-138d3ef5d965 47e211f4-33e3-42a4-b4a7-7eefea1ecc6f phoenixtestlab User Enabled 24 05e9a617-0261-4cee-bb44-138d3ef5d965 SPE_E3 {5517238f-2854-4e…
47e211f4-33e3-42a4-b4a7-7eefea1ecc6f_eda1941c-3c4f-4995-b5eb-e85a42175ab9 47e211f4-33e3-42a4-b4a7-7eefea1ecc6f phoenixtestlab User Enabled 1 eda1941c-3c4f-4995-b5eb-e85a42175ab9 POWERAUTOMATE_ATTENDED_RPA {30f4d888-2f5c-42.
Two weeks ago, i’ve tested and works well.
What version of the SDK are you using? I tested everything yesterday with V2.16 and it worked as expected. Are you using the script in https://github.com/12Knocksinna/Office365itpros/blob/master/RemoveServicePlan3.PS1.
Given the “no matching mailboxes” error, I suspect that you’re using the version based on the AzureAD module https://github.com/12Knocksinna/Office365itpros/blob/master/RemoveServicePlan2.PS1. That module is now deprecated and probably doesn’t work. Also, the script included a filter to select a small number of mailboxes to test against that should be removed to match conditions in your tenant. Did you do that? (I have removed the filter in the version posted to GitHub).
Every time I run your script – it returns ‘Total of 0 matching mailboxes found’ regardless of license or feature SKU selected. -> Same on my end. I’m using -> Using Azure AD cmdlets. It was working fine, 3 weeks ago.
Microsoft deprecated the AzureAD and MSOL modules on March 30, 2024. Have you tried the Graph SDK version?
the Azure AD cmdlets don’t work with licenses any more.