Microsoft 365 License Expiry Reports: 2026 Lifecycle Guide
Many Microsoft 365 administrators discover their subscription has expired when someone reports that Outlook has stopped functioning. Previously, there was some leeway owing to an ‘Expired’ grace state. However, since February 9, 2026, subscriptions purchased directly through a Microsoft Customer Agreement (MCA) no longer have this grace period. As a result, for numerous tenants, the end date on the invoice now marks the day users lose access to their accounts. The renewal process can lead to financial inefficiencies as well. A well-structured Microsoft 365 license expiry report can resolve both issues. This report clearly indicates the expiry dates, outlines the consequences upon expiry based on how the licenses were acquired, and helps determine the number of licenses to renew before incurring further costs.
Key Points to Remember
- Expiration and usage reports serve distinct purposes. Ensure both reports are available before any renewal.
- Subscriptions transition from Active to Expired, then to Disabled, and finally to Deleted. Once deleted, the subscription and its data cannot be restored.
- Subscriptions purchased under MCA lost the Expired grace state starting February 9, 2026.
- Grace periods vary based on the purchase method: typically, 30 days for most direct terms, 90 days for multi-year Enterprise Agreements or Volume Licensing, and 30 days for some Copilot VL subscriptions.
- Expiry dates can be retrieved from Billing > Your products or by using Get-MgDirectorySubscription (Get-MgSubscribedSku does not provide this information).
- Start taking action 90 days in advance. Cancellation windows often close long before the expiration date.
Understanding a Microsoft 365 License Expiry Report
A Microsoft 365 license expiry report details each subscription within your tenant, including its end date, lifecycle status, and renewal configuration, enabling you to decide what to renew, reduce, or allow to lapse before Microsoft does.
This report is curated at the subscription level rather than the user level. Each entry represents one SKU that youโve acquired, such as Microsoft 365 E3, Business Premium, or a Teams Phone add-on. It should also encompass trial versions and free SKUsโespecially trials, since they automatically initiate billing once they conclude.
Itโs important to differentiate this report from the license usage report, as they address different questions. The usage report indicates who holds a license and their level of activity, while the expiry report specifies when the contract for those licenses ends and the subsequent actions required. Relying solely on one of these reports is not advisable at renewal time. If you know the expiration date but not the usage levels, you may renew 500 seats when only 380 are necessary. Conversely, if youโre aware of the usage but not the expiration date, you may overlook potential wastage until after the cancellation period has ended.
The source of data can also be confusing. Most license scripts initiate from Get-MgSubscribedSku, which provides consumed units and pre-paid units, but omits expiry dates. For that, you need to utilise Get-MgDirectorySubscription. (Both aspects are elaborated upon in the how-to section below.)
A valuable expiry report answers three key questions:
- Which subscriptions are terminating, and when?
- What implications arise on that date based on your purchase method (MCA, Enterprise Agreement, Volume Licensing, or CSP)?
- How many licenses should you actually renew?
While many free scripts and admin tools can only address the first query, Turbo360 Tenant Manager provides a comprehensive view, combining expiry dates, license consumption, and associated costs for efficient analysis.
Consequences of Microsoft 365 Subscription Expiration
When a Microsoft 365 subscription expires, it navigates through four lifecycle states (Active, Expired, Disabled, and Deleted), and the duration of each state depends on the purchase method.
The second half of this explanation is crucial but often overlooked, and since February 2026, it has proven to be quite vital.
Lifecycle States Explained
Active: In this state, users can function normally, administrators can allocate licenses, and everything operates seamlessly.
Expired: Once the subscription surpasses its end date, users maintain full access to applications, emails, and files, often without realising the expiration has occurred. Administrators can reactivate the subscription from the admin center. This is the grace period that many refer to when they say, โwe have 30 days.โ
Disabled: At this stage, users can no longer access Microsoft 365 applications, and installed apps revert to a read-only mode, marked with Unlicensed Product notifications. Admins can still access the data, thus serving as a backup window. Although admins can sign in to the admin centre, they cannot allocate licenses under that subscription. However, reactivation remains permissible.
Deleted: At this point, the subscription and customer data are irretrievably deleted, and Microsoft Entra ID is removed if no other service relies on it. Reactivation is impossible, and purchasing a new subscription of the same nature later will not restore any lost data.
Understanding the MCA Subscription Change of February 2026
From February 9, 2026, license-based subscriptions acquired directly from Microsoft through a Microsoft Customer Agreement will bypass the Expired state entirely.
This alteration significantly impacts how you should interpret your reports. For these subscriptions, there is no quiet 30-day periodโonce the end date arrives, immediate action is required.
Microsoft offers the Extended Service Term (EST) as a solution for MCA customers needing more time. This allows the subscription to continue on a month-to-month basis post-termination until it is cancelled or converted to a standard subscription. This is particularly helpful if there are procurement delays in making renewal decisions. Hence, ensure your expiry report highlights MCA subscriptions well in advance.
Impact of Purchase Channel on Timeline
The same SKU can be subject to different timelines based on the purchase method. Hence, your report should include a channel column to avoid misconceptions about the expiry dates.
| Purchase Channel and Term | Expired (Grace Period) | Disabled | Subsequent Period |
| Direct from Microsoft, most offers | 30 days | 90 days | Deleted |
| Direct under MCA, license-based (from Feb 9, 2026) | None | Disabled period applies | Deleted |
| EA, Volume Licensing, or Open Value, monthly or annual term | 30 days | 90 days (called Inactive) | Deleted |
| EA, Volume Licensing, or Open Value, multi-year term | 90 days | 90 days (called Inactive) | Deleted |
| Some Microsoft 365 Copilot subscriptions via VL | 30 days only | As per agreement | Deleted |
| Cloud Solution Provider (CSP) | According to Partner Center policies | As per Partner Center policies | Deleted |
Itโs worth noting for agreement-based purchases that your actual end date might be linked to the agreementโs end date rather than the individual subscription term, and grace periods can differ by program. If you acquired your licenses via EA or VL, confirm these details with your licensing partner rather than solely relying on blog posts (including this one).
One important detail regarding Volume Licensing: A VL subscription only enters an Expired state once all licenses are removed. If you renew with fewer seats than previously held, it bypasses the Expired state and grants 90 days to reassess users assigned more licenses than currently ownedโwithout interruption for per-user subscriptions. Non-user subscriptions will react immediately; reducing the count on something like Office 365 Extra File Storage results in immediate storage reduction.
Circumstances Under Which the Grace Period Doesnโt Apply
Three specific scenarios can bypass the Expired state, and only one involves a policy revision:
- Canceling a monthly subscription within the cancellation window: This leads straight to the Disabled state, resulting in immediate loss of access for users while allowing admins to back up data.
- Explicitly deleting a subscription: This action bypasses both the Expired and Disabled states, with SharePoint Online and OneDrive data being deleted immediately. If someone on your team prematurely removes the subscription instead of allowing it to lapse, the data is irrecoverable.
- Being an MCA-direct customer after February 9, 2026: As highlighted previously.
Even after routine cancellation, the timeframe continues. Microsoft states any remaining data may be erased within 90 days, and at the latest, deletion occurs no later than 180 days post-cancellation.
Thus, the key question your expiry report must answer is not merely โwhen does this end?โ but also โwhich of these rules pertains to this entry?โ
How to Verify Microsoft 365 License Expiry Dates
The expiry dates of Microsoft 365 licenses can be checked in the admin center under Billing > Your products, by using the Get-MgDirectorySubscription PowerShell cmdlet, or through the Microsoft Graph /directory/subscriptions endpoint.
The admin center serves well for a quick glance. However, for ongoing tracking, PowerShell or Graph is more suitable.
Accessing the Admin Center
Log in with at least the Billing admin role (Global admin access is not necessary for this task). Navigate to Billing > Your Products. Here, each subscription displays its status and expiry date, along with the option to check if recurring billing is enabled.
This method is swift, but it only provides a screen view rather than a detailed report. Sorting through a tenant with 40 subscriptions by end date is impossible, scheduling reports is not feasible, and there is no information on user utilization.
Utilising PowerShell (Get-MgDirectorySubscription)
The Microsoft Graph PowerShell SDK offers the same data presented in a format that can be sorted, filtered, and exported. All you need is read-only access.
Connect-MgGraph -Scopes "Organization.Read.All"
Get-MgDirectorySubscription |
Select-Object SkuPartNumber, Status, IsTrial, TotalLicenses,
CreatedDateTime, NextLifecycleDateTime |
Sort-Object NextLifecycleDateTime
The critical field is NextLifecycleDateTime, but it should be interpreted alongside Status. This indicates when the subscription transitions to its next stateโthis date is not always the one youโd label as โexpiry.โ For an active subscription, it signals the term end. If a subscription is already expired, it details when it turns disabled. A report that presents just the date without the accompanying status may provide misleading insights.
Recall the earlier caution: Get-MgSubscribedSku does not feature expiry dates. However, it includes details that the subscription object lacks, particularly how many units are allocated. By integrating both data sources, your report gains real utility:
$assigned = @{}
Get-MgSubscribedSku | ForEach-Object { $assigned[$_.SkuId] = $_.ConsumedUnits }
Get-MgDirectorySubscription | ForEach-Object {
[pscustomobject]@{
Sku = $_.SkuPartNumber
Status = $_.Status
Trial = $_.IsTrial
Purchased = $_.TotalLicenses
Assigned = $assigned[$_.SkuId]
NextLifecycle = $_.NextLifecycleDateTime
}
} | Sort-Object NextLifecycle |
Export-Csv .\m365-expiry-report.csv -NoTypeInformation
One final note: ConsumedUnits are counted per SKU, not per subscription. If you have two subscriptions for the same SKU (for example, an annual E3 and a monthly top-up), both entries will reflect the same assigned total. Itโs advisable to mark these entries for individual review.
Accessing via Microsoft Graph API
For automation purposes, you can directly invoke the Graph API:
GET https://graph.microsoft.com/v1.0/directory/subscriptions
This request returns the same companySubscription objects in JSON format: SKU, status, trial flag, total licenses, and nextLifecycleDateTime. The least privilege application permission required is Organization.Read.All. For delegated access, a reader role, such as Global Reader or Directory Readers, is sufficientโthereโs no need for Global admin rights to run the report.
This method is optimal if you need to deliver reports directly to someoneโs inbox, update a dashboard, or generate alerts within 90 days of expiry. Running it from an Azure Automation runbook with a managed identity eliminates the necessity to store credentials. (The automation setup will be detailed in the relevant section.)
Selecting the Appropriate Method
| Method | Least Privilege Access Required | Data Provided | Can Be Scheduled | Best Suited For |
| Admin Center | Billing Admin | Status, end date, recurring billing, one subscription at a time | No | Quick checks in small tenants |
| PowerShell | Organization.Read.All | Status, NextLifecycleDateTime, trial flag, purchased and assigned units, CSV export | By using a scheduler or runbook | Monthly reports for a single tenant |
| Graph API | Organization.Read.All (Application) | The same fields as JSON, ready for integration with other systems | Yes | Alerts, dashboards, multi-tenant management |
Regardless of the method chosen, the challenge lies not in gathering the dates but in determining what columns should be included in the report to facilitate actionable responses.
Components of a License Expiry Report
A comprehensive Microsoft 365 license expiry report should list each subscriptionโs end date, lifecycle status, purchase channel, seat counts, actual usage, costs, and responsible owner, thus ensuring each entry concludes with a renewal decision.
Most reports only highlight the expiry date, indicating when an issue arises, rather than providing solutions.
Below is a suggested column structure that stands up well in real renewal discussions. Some data can be directly pulled from Graph, while others need to be manually added, which is standard: the parts not supplied by Graph often include financial details that finance teams care about.
| Column | Source | Importance |
| SKU / Subscription Name | Graph (skuPartNumber) or Admin Center | The user-friendly name assists finance in understanding the data. For example, mapping part numbers like SPE_E3 to โMicrosoft 365 E3.โ |
| Purchase Channel | Admin Center, Invoice, or Partner | Determines applicable lifecycle rules: MCA direct, EA/VL, or CSP. |
| Term and Billing Frequency | Admin Center or Invoice | Monthly, annual, or multi-year terms affect grace periods and reduction opportunities. |
| Status | Graph (status) | Informs how to interpret expiry dates. |
| Next Lifecycle Date | Graph (nextLifecycleDateTime) | Indicates the date when an event occurs. |
| Days Remaining | Calculated | Facilitates report sorting and highlights urgency around 30, 60, and 90 days. |
| Recurring Billing | Admin Center | If enabled, subscription renews automaticallyโsometimes, this is undesirable. |
| Cancellation Window | Purchase Terms | Indicates whether cancellation or reductions are still feasible. Once this window closes, obligations until the end of term ensue. |
| Trial Status | Graph (isTrial) | Trials automatically convert into paid subscriptions. |
| Purchased Units | Graph (totalLicenses) | Represents whatโs being paid for. |
| Assigned Units | Graph (consumedUnits, via Get-MgSubscribedSku) | Highlights the number of licenses distributed. |
| Active Users | Microsoft 365 Usage Reports | Reflects actual usage. This metric is crucial for savings. |
| Annual Cost | Invoice or Price Sheet | Translates seat differences into financial terms that prompt action. |
| Owner | Your Organisation | Identifies who approves renewals. Rows lacking an owner typically proceed to auto-renew. |
| Renewal Decision | Your Organisation | Choices include renewing, reducing, switching SKU, opting for EST, or allowing the subscription to expire. |
Several columns merit additional explanation:
Purchased, Assigned, and Active counts represent three distinct figures. The difference between Purchased and Assigned reflects shelfwareโlicenses not in use. Meanwhile, the difference between Assigned and Active indicates quieter wasteโlicenses assigned to individuals who have departed, changed roles, or failed to utilise the application. Most tenants encounter both issues, but the latter is often more challenging to detect, as the license appears โin use.โ
The Cancellation Window column is frequently overlooked. For certain subscriptions, cancellation rights apply only over a brief window post-purchase or renewal. After this period, disabling recurring billing stops only the next renewal. A report must indicate when that window closes, not just when the term finishes, or you could encounter waste that remains costly until the next renewal cycle.
Including Owner and Decision transforms the report into a more actionable document. A row that reads โE3, 500 purchased, 412 assigned, 371 active, ends in 74 days, owner: IT Ops, decision: reduce to 400โ provides a clear course of action. Alternatively, a row lacking the last two fields leaves the reader uncertain of the necessary follow-up.
Itโs generally advisable for usage and costs to reside within the same report as expiry dates. Relying on separate scripts for usage, dates from another source, and prices from invoices can cause reports to lose relevancy over time, raising the issue of timing.
When to Address an Expiring License
Take action on an expiring Microsoft 365 license at least 90 days before its end date, with review points at 90, 60, and 30 days, as decisions on cancellations and seat reductions need to be finalised long before the subscription concludes.
Your team often waits until 30 days prior; however, this is when many options may already be unavailable.
By the time you reach the 30-day mark, procurement likely has a quote underway, recurring billing remains active, and licence usage might not have been thoroughly examined. Renewal tends to proceed based on the previous yearโs seat count if no reductions are discussed. Microsoft sends notification emails and alerts in the admin centre as expiration nears, yet these messages go to billing admins, who may not have insight into whether a specific number of Visio seats is still necessary.
Therefore, establish a timeline leading back from the expiry date.
90 Days Ahead: Identify Wastage. Obtain the report and compare purchased, assigned, and active seats for all subscriptions set to expire this quarter. Reclaim licenses from departing employees and inactive accounts now to lower the assigned count before any renewal quotations are generated. Also, look for any trials concluding during this timeframe, as they will start accruing charges unless deactivated.
60 Days Ahead: Make Decisions. Assign an owner to each row and determine whether to renew, reduce, switch SKUs, transition to EST, or let the subscription expire. Finance should be involved at this stage; the admin understands usage, while finance comprehends the budget. Both departments should collaborate, be it in person or via spreadsheet, to make informed decisions.
30 Days Ahead: Action and Confirmation. Adjust seat counts, align recurring billing with the determined decisions, and verify with your partner if your purchase was through one. Any unresolved items at this point should be escalated to avoid defaulting on decisions.
Day of Expiry and After: Validate Status Changes. Verify that subscriptions have transitioned as expected. If a subscription was meant to lapse, ensure that it is in the correct state and check that all necessary data has been backed up. Avoid deleting subscriptions simply to tidy up the billing page, as discussed earlier.
Assigning Responsibility at Each Checkpoint
Responsibilities typically lie with multiple individuals, leading to missed expirations.
The M365 admin handles data-related aspects, including seat counts, usage, license reclaiming, and the technical implications of lapses. Conversely, the finance or billing owner oversees monetary concerns, including the budget, invoices, and ensuring reductions are reflected in upcoming bills. In cases where licenses are purchased via EA or a CSP, your licensing partner also has a role in the timeline, necessitating advance notice for any adjustments.
Itโs crucial to designate a singular owner for each subscription, even if multiple individuals are involved. Labels like โITโ should not be used.
Adjusting the Timeline According to Purchase Channels
While 90 days is recommended as a guideline, it is not a strict rule.
EA and Volume Licensing renewals tend to require more lead time. As these often involve negotiation with a partner and a true-up process, consider starting the 90-day review in the previous quarter for significant agreements. CSP subscriptions adhere to their partner’s terms, and their cancellation windows can be brief, so itโs best to consult your partner for precise dates rather than make assumptions.
MCA-direct subscriptions should be monitored closely now that they no longer offer an Expired grace period. If critical decisions are not made by the end date, the Extended Service Term is the only avenue for gaining additional timeโand this must be selected before the term’s conclusion.
By aligning the timings correctly, the 90-day review transforms from being a mere cleanup task into a proactive measure that can significantly reduce costs.
Automating Microsoft 365 License Expiry Reporting
To automate Microsoft 365 license expiry reporting, execute a Microsoft Graph PowerShell script as an Azure Automation runbook using a managed identity, enable read-only Organization.Read.All access, and schedule it to flag licenses that are expiring within the next 90 days.
This approach eliminates the need for stored passwords, app secrets that need refreshing, or any requirement for a laptop to remain operational.
If your FinOps team works within Azure, it serves as an ideal environment for this. The runbook will reside within a subscription you already manage, consolidating it with your existing cost tools. Also, it ensures M365 licensing receives the same level of scrutiny as your Azure spend, rather than languishing in someoneโs Downloads folder.
Step 1: Create the Automation Account and Identity
First, set up an Azure Automation account with a system-assigned managed identity enabled. Then, import two essential modules as resources: Microsoft.Graph.Authentication and Microsoft.Graph.Identity.DirectoryManagement. The latter module contains the cmdlets required for handling subscriptions and SKUs. Omitting this step will lead to failures in your runbook.
Step 2: Provide Graph Permissions
This step often confounds users. Although the Entra admin center displays a managed identityโs permissions, it won’t let you assign Graph application permissions directly. Instead, execute this once from your workstation using PowerShell:
Connect-MgGraph -Scopes "AppRoleAssignment.ReadWrite.All","Application.Read.All"
$graph = Get-MgServicePrincipal -Filter “AppId eq ‘00000003-0000-0000-c000-000000000000′”
$mi = Get-MgServicePrincipal -Filter “displayName eq ‘your-automation-account'”
$role = $graph.AppRoles | Where-Object {
$_.Value -eq “Organization.Read.All” -and
$_.AllowedMemberTypes -contains “Application” }
New-MgServicePrincipalAppRoleAssignment -ServicePrincipalId $mi.Id `
-PrincipalId $mi.Id -ResourceId $graph.Id -AppRoleId $role.Id
Apply Organization.Read.All permissions onlyโthereโs no need to grant Directory.Read.All โjust in case.โ
Step 3: Develop the Runbook
Create a PowerShell 7 runbook. This should incorporate the same logic as the export script mentioned earlier, with an added calculation for days remaining and essential filtering for relevant rows:
Connect-MgGraph -Identity -NoWelcome
$assigned = @{}
Get-MgSubscribedSku | ForEach-Object { $assigned[$_.SkuId] = $_.ConsumedUnits }
$today = Get-Date
$report = Get-MgDirectorySubscription | ForEach-Object {
$daysLeft = if ($_.NextLifecycleDateTime) {
[int]($_.NextLifecycleDateTime – $today).TotalDays } else { $null }
[pscustomobject]@{
Sku = $_.SkuPartNumber
Status = $_.Status
Trial = $_.IsTrial
Purchased = $_.TotalLicenses
Assigned = $assigned[$_.SkuId]
NextLifecycle = $_.NextLifecycleDateTime
DaysLeft = $daysLeft
}
}
$flagged = $report | Where-Object {
($_.DaysLeft -ne $null -and $_.DaysLeft -le 90) -or
$_.Trial -or $_.Status -ne “Enabled”
} | Sort-Object DaysLeft
$flagged | Format-Table -AutoSize
This filter captures anyone within the 90-day window, all trials (due to automatic billing), and any subscriptions not currently “Enabled.” The latter signifies that a subscription has already expired, and no one noticed.
Step 4: Schedule and Direct the Output
Establish a schedule for the runbook. A monthly cadence suffices for complete reports, while a weekly schedule is better suited for monitoring licenses entering the 90-day timeframe.
Then, direct the output to a location where the relevant stakeholders can access it. Writing the CSV to a storage account is acceptable, but sending it to a Teams channel typically garners better visibility, as it’s more likely to be read. If you choose to email it, ensure the identity has Mail.Send permissions, limiting this access to a specific sending mailbox instead of broadly across the tenant.
Encapsulating Limitations of the Script
Be forthcoming about the scope of what this process covers. The runbook provides dates, statuses, trials, and comparisons between purchased versus assigned licenses, which is already more than what most tenants currently track.
However, it does not capture details like purchase channel, cancellation windows, pricing for each seat, nor who is genuinely utilising their license versus those merely listed as having one. For those overseeing multiple tenants, you’ll need to establish a runbook, identity, and permission grants for each one separately.
This gapโbetween identifying which licenses are expiring and discerning which are worth renewingโis precisely why Turbo360 Tenant Manager was developed. It evaluates every SKU within the tenant (including paid, free, and trial versions) for consumption and optimal sizing to initiate renewal discussions grounded in usage data rather than relying on last year’s seat figures.
Share this content:
Discover more from Qureshi
Subscribe to get the latest posts sent to your email.