Where your Microsoft 365 storage actually goes: a read-only audit in four layers
The storage bar in the SharePoint admin center gives you one number: used versus total. The renewal conversation needs four: how much of that is live files, how much is version history, how much is deleted-but-not-purged, and how much is compliance copies you cannot touch. None of the four is on the bar. This is how to get all of them without changing anything in the tenant, with the exact commands and reports, and what each bucket is worth once you have it.
Layer 0: the number that bills
Start with the pool, because every other number is only interesting relative to it. The tenant's SharePoint quota is 1 TB plus 10 GB per qualifying licence, plus any Extra File Storage add-on. Microsoft calculates it in binary gigabytes (1 GB = 230 bytes), which matters when you compare against a vendor invoice in decimal. Three things are not in the pool, and people routinely add them in by mistake:
- OneDrive accounts. Each user's OneDrive has its own per-user quota (the 1 → 5 → 25 TB ladder from the Plan 2 write-up). They show up in the OneDrive usage report, not on the Active sites bar.
- Archived sites. Content in Microsoft 365 Archive is still SharePoint storage, but it does not count toward the active quota. It is billed on its own meter.
- Deleted sites in the recycle bin. They do not count toward the organisation's total. Deleted files inside live sites are a different story; see Layer 2.
Read it from the SharePoint Online Management Shell, which needs SharePoint Administrator and changes nothing:
Connect-SPOService -Url https://TENANT-admin.sharepoint.com
Get-SPOTenant | Select-Object StorageQuota, StorageQuotaAllocated # MB
The same figures are on the Active sites page (top right) and under Reports → Usage → SharePoint → Storage in the Microsoft 365 admin center. Two caveats from Microsoft's own docs: the admin center bar lags real usage by 24–48 hours, and the Storage report refreshes every 48–72 hours. If you cleaned something up yesterday and the bar has not moved, that is why. The report also puts a banner up at 80% of quota, which is the point at which most people start this exercise.
Layer 1: which sites
Storage follows a Pareto curve in almost every tenant: a handful of sites hold most of it. Get the per-site list with sizes, quotas, last change, template and archive state in one call:
Get-SPOSite -Limit All -Detailed |
Select-Object Url, Template, StorageUsageCurrent, StorageQuota,
LastContentModifiedDate, ArchiveState |
Sort-Object StorageUsageCurrent -Descending |
Export-Csv .\sites.csv -NoTypeInformation
StorageUsageCurrent and StorageQuota are in MB. Sites in the recycle bin are not returned, which is correct for this purpose because they are not billed. If you also want OneDrives in the same file, add -IncludePersonalSite $true, but keep them in a separate column in your analysis; they are not in the pool.
The Graph usage report gives you the same list with two columns PowerShell does not: Last Activity Date and Active File Count. Pull reports/getSharePointSiteUsageDetail(period='D180') with Reports.Read.All; it redirects to a CSV with Site URL, Owner, Is Deleted, Last Activity Date, File Count, Active File Count, Storage Used (Byte), Storage Allocated (Byte) and Root Web Template. Note that names are anonymised by default in usage reports; a global or reports admin has to untick Conceal user, group and site names under Org settings → Reports before the CSV shows real URLs.
What you are looking for at this layer:
| Pattern | What it usually is | Layer 2 check |
|---|---|---|
| Top 10 sites hold >60% of the pool | Normal. These are the only sites worth auditing in depth. | Version report on each |
| Large site, Last Activity Date > 12 months ago | Cold departmental data, migrated project, or a departed team's Team | Archive candidate; confirm no retention policy blocks it |
| Storage used far above what the file count suggests | Version history or a Preservation Hold library | Storage metrics page |
Template = GROUP#0 or TEAMCHANNEL#1 with recordings | Channel meeting recordings in Documents/Recordings | Check the expiry policy |
Layer 2: inside a site, five buckets
A site's storage figure is the sum of five things. Only the first is what users think of as "our files".
| Bucket | What it is | Counts toward site storage? |
|---|---|---|
| Current files | The latest version of every file in every library | Yes |
| Version history | Every previous version. Each one is a full copy of the file, not a delta | Yes |
| First-stage recycle bin | What users deleted in the last 93 days | Yes |
| Second-stage recycle bin | What was purged from the first stage, until day 93 | Not in the storage-used metric (subsites are the exception). Capped at 200% of the site quota |
| Preservation Hold library | Hidden library holding copies of edited or deleted files that a retention policy or hold covers | Yes |
Plus site metadata (file properties, list data, version records), which counts and has its own 1,000 GB per-site limit, though it rarely gets there.
Measuring each bucket, read-only
Storage metrics page. On any site, /_layouts/15/storman.aspx (Site settings → Storage metrics). It lists every library including the hidden Preservation Hold Library with its size, and warns when the site nears the metadata limit. This is the fastest way to see whether a 3 TB site is 3 TB of documents or 800 GB of documents plus 2.2 TB of retained copies. Site collection admin permission is enough.
Version history. Microsoft ships a report job that writes a CSV of every version with its size to a location on the site. It runs asynchronously and deletes nothing:
New-SPOSiteFileVersionExpirationReportJob -Identity https://TENANT.sharepoint.com/sites/finance `
-ReportUrl "https://TENANT.sharepoint.com/sites/finance/Shared Documents/VersionReport.csv"
Get-SPOSiteFileVersionExpirationReportJobProgress -Identity https://TENANT.sharepoint.com/sites/finance `
-ReportUrl "https://TENANT.sharepoint.com/sites/finance/Shared Documents/VersionReport.csv"
There is a library-scoped variant (New-SPOListFileVersionExpirationReportJob -Site … -List …) for when one library is the obvious culprit. Sum the size column by library and you know exactly what a trim would reclaim before you queue one. Microsoft's own tutorial pairs this with a "what-if" analysis of different version limits.
Recycle bins. The first-stage bin is visible to any site member; the second-stage bin to site collection admins. Both are on the site's Recycle bin page. For sizes across many sites, the PnP PowerShell community module's Get-PnPRecycleBinItem returns items with sizes per stage; it is not a Microsoft-supported module, so treat it as a convenience, not the system of record.
Preservation Hold library. Its size is on the storage metrics page. Whether it is growing is a Purview question: which retention policies target this site. Get-RetentionCompliancePolicy | Where-Object { $_.SharePointLocation -or $_.OneDriveLocation } in Security & Compliance PowerShell lists them.
Layer 3: what each bucket is worth
This is the part the audit exists for. The same gigabyte means something different depending on which bucket it sits in, because the mechanism that reclaims it is different for each.
| Bucket | Reclaim mechanism | Blocked by | Timing |
|---|---|---|---|
| Version history | Version-history limits for new versions; a trim job (New-SPOSiteFileVersionBatchDeleteJob) for existing ones | Retention policy or eDiscovery hold: the trim stamps an expiration date instead of deleting, and the version stays until the hold lifts | Trim runs asynchronously; purge of expired versions can take a couple of days |
| First-stage recycle bin | Nothing, if you can wait: items are gone at day 93. Emptying it is instant and irreversible | Retention: deleted items under policy went to the Preservation Hold library first | Immediate on empty; storage bar updates in 24–48 h |
| Preservation Hold library | Only a change to the retention policy that fills it. The cleanup job runs every 7 days and skips anything under 30 days old, so up to 37 days after expiry | The policy itself. Version trimming never touches it | Weeks |
| Cold sites (no activity 12+ months) | Microsoft 365 Archive: the site leaves the active pool and bills at $0.05/GB/month list instead of $0.20/GB/month for add-on storage above the pool | Holds still apply; readers can reactivate | Archived storage stops counting toward the active quota; bar updates in up to 48 h |
| Channel meeting recordings | Teams recording expiry policy (default 120 days, then recycle bin). Applies to new recordings only | Recordings moved out of their original folder lose the expiry stamp | Per policy |
Two things people expect to be on this list are not. Meeting recordings for ordinary (non-channel) meetings land in the organiser's OneDrive, which is outside the pool; they are a OneDrive quota problem, not a SharePoint one. And departed users' OneDrives are on the unlicensed-account lifecycle and its own $0.05/GB meter, which we covered separately. Both belong in the same audit, but in a different column.
Worked example
Hypothetical tenant, 300 qualifying licences. Pool = 1 TB + 300 × 10 GB ≈ 3.9 TB. Active sites bar shows 5.3 TB used, so roughly 1.4 TB above the pool, which on the pay-as-you-go SharePoint Storage meter at $0.20/GB list is about $280/month if nothing changes. The four layers turn that into a decision:
- Layer 1: eight sites hold 4.1 TB. Three of them have had no activity in 14 months (1.6 TB between them).
- Layer 2, versions: the version report on the top five active sites totals 1.1 TB of previous versions, 700 GB of it in two design libraries where every save is a 200 MB file.
- Layer 2, bins: first-stage recycle bins across the top eight hold 180 GB, all of it inside the 93-day window.
- Layer 2, PHL: the finance site's Preservation Hold library is 400 GB under a 7-year retention policy. Untouchable, and correctly so.
Layer 3 then says: archive the three cold sites (1.6 TB off the active pool, about $80/month on the archive meter instead of counting against it), trim versions on the two design libraries after confirming no hold covers them (700 GB back), and leave the bins and the PHL alone. That takes the tenant from 1.4 TB over to roughly 1 TB under the pool, and the add-on purchase that was on the renewal agenda comes off it. The 400 GB of retained copies stays, but now it is a known, defensible number rather than a mystery inside "finance is 1.8 TB".
Checklist
Get-SPOTenant: quota and allocated. Write both down with the date; the bar lags.Get-SPOSite -Limit All -Detailedto CSV; sort byStorageUsageCurrent. Take the top ten.- Graph
getSharePointSiteUsageDetail('D180')for Last Activity Date on the same sites. Anything over 12 months with no hold is an archive candidate. - Storage metrics page on each of the top ten: split into files, Preservation Hold library, recycle bin.
- Version expiration report job on each of the top ten. Sum by library.
Get-RetentionCompliancePolicyso you know which sites are hold-bound before proposing any trim.- Present four numbers, not one: live, versions, bins, retained. Each has a different owner and a different lever.
Free: pool position, top sites and departed-user OneDrives in one run
StorageScout Lite is a read-only PowerShell audit that does Layer 0 and Layer 1 for you and exports every departed-user OneDrive with its size. No server, nothing leaves your tenant. The paid tiers add the Layer 2 breakdown per site, dollar-quantified against the meters above.
Download StorageScout Lite — free See what Solo addsDisclosure: StorageScout is our product. Prices are Microsoft's public US list prices as documented on Microsoft Learn at the time of writing; your agreement, region and currency may differ. The worked example is hypothetical. StorageScout is independent and not affiliated with or endorsed by Microsoft.
Sources
- SharePoint limits — pool formula, binary GB, metadata limit, recycle bin counts toward the organisation's limit
- Manage site storage limits — Active sites bar, 24–48 h lag, deleted sites excluded
- SharePoint Storage report — 48–72 h refresh, 80% banner
- SharePoint Online out of storage space — archived data does not count toward the active quota
- Get-SPOSite and Get-SPOTenant — properties and permissions
- reportRoot: getSharePointSiteUsageDetail — CSV columns
- SharePoint site usage report — Last activity date definition, anonymised names
- Restore deleted items from the site collection recycle bin — 93 days, first vs second stage and the storage-used metric, 200% cap
- Learn about retention for SharePoint and OneDrive — Preservation Hold library behaviour, 30-day minimum and 7-day timer
- Generate version storage usage report and Versions FAQ — report cmdlets, trim vs holds, purge timing
- SharePoint storage planning — version trimming does not affect the Preservation Hold library
- Site at or near the metadata limit — metadata counts toward site storage
- Teams meeting recording storage and recording expiration policy — OneDrive vs channel site, 120-day default
- Pay-as-you-go pricing — Storage services — $0.20/GB/month SharePoint storage, $0.05/GB/month Archive