Microsoft 365

SharePoint version history limits: automatic and count-based trimming

Cut SharePoint and OneDrive storage used by old file versions: set automatic or count limits at tenant, site and library level, model the impact, then trim existing versions safely.

13 min read
On this page

To reduce the storage SharePoint and OneDrive spend on old file versions, switch new libraries to the automatic version history limit (or a count and expiration limit) at organization level, apply the same limit to existing libraries per site with Set-SPOSite, and then queue a trim job with New-SPOSiteFileVersionBatchDeleteJob to remove the versions that already exceed it. Changing a limit never deletes existing versions on its own, and a trim job deletes permanently, bypassing the recycle bin, so generate a version usage report and run a what-if analysis on it first. The rest of this guide walks through each step, with the PowerShell for every scope.

Who this is for and what you will have

This guide is for SharePoint administrators whose tenant is near its storage limit, who are recalculating storage after a licensing change, or who want to stop version history from growing without bounds. At the end you will have:

  • A clear choice between automatic, count-only and count-plus-expiration limits.
  • An organization default for new libraries and new OneDrive accounts.
  • Site and library limits applied to existing content where you need them.
  • A version usage report and a what-if analysis showing how much each option would free.
  • Trim jobs queued, tracked and verified on the sites that matter.

If you are recalculating storage because standalone SharePoint or OneDrive licenses are going away, the standalone plan retirement guide covers the licensing side.

How version limits work

Limits are set at three levels and inherit downward to new libraries:

LevelApplies toWhere to set it
OrganizationNew document libraries on existing and new sites, and default libraries on new OneDrive accountsSharePoint admin center or Set-SPOTenant
SiteNew libraries on that site, and optionally existing onesPowerShell only (Set-SPOSite)
LibraryFiles stored in that libraryLibrary versioning settings or Set-SPOListVersionPolicy

When a library is created, SharePoint checks for a site-level setting first and falls back to the organization setting. The organization default, unless you change it, is manual limits with 500 major versions and no expiration.

The three modes

ModeBehaviorTrade-off
Automatic (recommended by Microsoft)Keeps more recent versions and fewer older ones, based on version ageOptimizes storage without you choosing numbers; versions at key points stay available even on files nobody edits
Manual, count and expirationDeletes versions beyond the count or older than the expirationLowest storage use; a file not edited for longer than the expiration loses all its versions
Manual, count onlyKeeps the configured number of versions regardless of agePredictable, but can use a lot of storage on heavily edited files

Under automatic limits, users have access to:

  • All versions, within the 500 count limit, for the first 30 days.
  • Hourly versions (the version at the top of each hour) from 30 to 60 days.
  • Daily versions from 60 to 180 days.
  • Weekly versions beyond 180 days, kept until the 500 count limit is reached.

Microsoft's own examples show automatic limits cutting version storage by roughly 94 to 96 percent compared with count limits alone for files with steady edit activity. Your result depends on edit patterns, which is why the what-if step later in this guide matters.

What deletes and what doesn't

EventWhat happens to versions
A user deletes a version from a file's historyGoes to the site recycle bin and can be restored
Versions exceed the library's limitsPermanently deleted, bypassing the recycle bin
A trim job runsPermanently deleted, bypassing the recycle bin
Item is under a retention policy or eDiscovery holdLibrary limits are ignored until the retention period ends or the hold is released
A trim job reaches a version under retention or holdStamps an expiration date instead of deleting; deletes later only if the policy or hold has lifted
Site is read-only or lockedTrimming of expired versions is suspended until the site is unlocked
Item has a retention label but no retention policy or holdLimits apply, but users still can't delete versions themselves
Document is marked as a recordVersion deletion is blocked

Two more behaviors are easy to miss. Lowering a library's count limit doesn't remove excess versions at once; they are trimmed gradually, up to 20 versions each time the file gets a new version. Changing the expiration on a library applies only to versions created after the change, because the expiration date is stamped on a version when the version is created.

Prerequisites

  • SharePoint Administrator or Global Administrator role.
  • The latest SharePoint Online Management Shell. Microsoft's instructions say to uninstall older versions first.
  • PowerShell 7 on the machine where you analyze the report; Microsoft's analysis scripts use PowerShell 7 syntax.
  • A document library on each site you analyze where the report CSV can be written. The report location must be inside a SharePoint document library, and no file with the same name can already exist there.
  • A recovery decision: how far back users must be able to restore, and whether a backup such as Microsoft 365 Backup covers anything you are about to trim.
  • For tenant-wide trimming only: a SharePoint Advanced Management or Copilot license. That feature is in private preview.
Connect-SPOService -Url https://contoso-admin.sharepoint.com

Step 1: Set the organization default for new libraries

In the SharePoint admin center, go to Settings and select Version history limits.

  • For automatic limits, select Automatically, then Save and Confirm.
  • For count-only limits, select Manually, enter a value between 100 and 50,000 in Number of major versions, and set Delete versions after this period of time to Never.
  • For count and expiration, select Manually, enter the count, and choose a preset period or a custom value greater than 30 days.

The PowerShell equivalents:

# Automatic limits for all new libraries and new OneDrive accounts
Set-SPOTenant -EnableAutoExpirationVersionTrim $true
 
# Or manual: 500 major versions, delete versions older than 365 days (0 = never expire)
Set-SPOTenant -EnableAutoExpirationVersionTrim $false -MajorVersionLimit 500 -ExpireVersionsAfterDays 365
 
# Review the current default
Get-SPOTenant | Select-Object EnableAutoExpirationVersionTrim, ExpireVersionsAfterDays, MajorVersionLimit

You can also set a separate limit for specific file types. Microsoft's example keeps 100 major versions and 30 days for audio and video files:

Set-SPOTenant -MajorVersionLimit 100 -ExpireVersionsAfterDays 30 -EnableAutoExpirationVersionTrim $false -FileTypesForVersionExpiration @("audio", "video")

The change can take up to 24 hours to reach new libraries. It doesn't update existing libraries and doesn't trim existing versions; there is no organization-level option for either outside the tenant-level preview described later. In multi-geo tenants, set the organization limit for each geo.

The admin center doesn't accept fewer than 100 versions or fewer than 30 days. The APIs do, but Microsoft warns that values below those can cause accidental data loss from normal user activity.

Step 2: Measure version storage on a site

Before changing anything on existing content, find out how much space versions take and what each mode would free. Queue a report job for a site or a single library:

$site   = "https://contoso.sharepoint.com/sites/projects"
$report = "https://contoso.sharepoint.com/sites/projects/Shared Documents/Reports/VersionReport.csv"
 
# Whole site
New-SPOSiteFileVersionExpirationReportJob -Identity $site -ReportUrl $report
 
# Or one library
New-SPOListFileVersionExpirationReportJob -Site $site -List "Documents" -ReportUrl $report
 
# Check progress of a site report (repeat until status is "completed")
Get-SPOSiteFileVersionExpirationReportJobProgress -Identity $site -ReportUrl $report
 
# Or of a library report
Get-SPOListFileVersionExpirationReportJobProgress -Site $site -List "Documents" -ReportUrl $report

The progress cmdlets return JSON with a status of completed, in_progress, no_report_found or failed (with an error_message). On large sites the job can take a few days.

Each row of the CSV is one file version. The columns that matter for analysis are Size (bytes), SnapshotDate (when the version became historical), CurrentExpirationDate, AutomaticPolicyExpirationDate and TargetExpirationDate. Columns ending in .Compact, such as WebId.Compact and FileUrl.Compact, are left empty when the value repeats the row above, so fill them down before grouping by file. Versions in the Preservation Hold library are included.

Step 3: Run a what-if analysis

Download the CSV, fill TargetExpirationDate according to the mode you are considering, then analyze it. Microsoft publishes scripts for each mode. The automatic one is short: it copies the automatic policy date into the target column.

# ScheduleUpdate_Auto.ps1 (from Microsoft's what-if tutorial, PowerShell 7)
param (
  [Parameter(Mandatory=$true)][string]$ImportPath,
  [Parameter(Mandatory=$true)][string]$ExportPath
)
 
$Schedule = Import-Csv -Path $ImportPath
$Schedule | ForEach-Object { $_.TargetExpirationDate = $_.AutomaticPolicyExpirationDate }
$Schedule | Export-Csv -Path $ExportPath -UseQuotes AsNeeded -NoTypeInformation

The tutorial also has ScheduleUpdate_ExpireAfter.ps1 for expiration limits and ScheduleUpdate_Count.ps1 for count limits. Feed the output into Microsoft's AnalyzeReportFile.ps1 script or the AnalyzeReportFile_Template.xlsx workbook. Either one shows:

  • The number and size of versions that expire over time under the current schedule and under the target schedule.
  • Files that would drop below a threshold number of versions (10 by default).
  • The users whose versions would be deleted.

For a quick total before you run the full analysis, sum the size of versions whose target date is already in the past, since those are the ones a trim job deletes immediately:

$rows = Import-Csv .\VersionReport_Auto.csv
$now  = Get-Date
$gone = $rows | Where-Object { $_.TargetExpirationDate -and ([datetime]$_.TargetExpirationDate -le $now) }
 
"{0:N0} versions, {1:N1} GB freed immediately" -f $gone.Count,
    (($gone | Measure-Object Size -Sum).Sum / 1GB)

Any target date in the past means that version is deleted as soon as the trim starts. Share the "files with fewer versions" and "users impacted" output with site owners before you commit.

Step 4: Apply limits to existing libraries on a site

Site-level limits can only be set with PowerShell. Choose whether they apply to new libraries, existing libraries, or both.

$site = "https://contoso.sharepoint.com/sites/projects"
 
# Automatic limits on all new and existing libraries in the site
Set-SPOSite -Identity $site -EnableAutoExpirationVersionTrim $true
 
# Only existing libraries; new libraries keep inheriting the organization default
Set-SPOSite -Identity $site -EnableAutoExpirationVersionTrim $true -ApplyToExistingDocumentLibraries
 
# Manual count with no expiration on all libraries in the site
Set-SPOSite -Identity $site -EnableAutoExpirationVersionTrim $false -MajorVersionLimit 300 -MajorWithMinorVersionsLimit 10 -ExpireVersionsAfterDays 0
 
# Check the settings and the background job for existing libraries
Get-SPOSite -Identity $site | Format-List Url, EnableAutoExpirationVersionTrim, ExpireVersionsAfterDays, MajorVersionLimit
Get-SPOSiteVersionPolicyJobProgress -Identity $site

-MajorWithMinorVersionsLimit is the number of major versions for which all minor (draft) versions are kept; it matters only in libraries that create minor versions. Microsoft's count-limit examples, for both site limits and trim jobs, supply -MajorVersionLimit and -MajorWithMinorVersionsLimit together; follow the same pattern. Updates to existing libraries run as a background job that can take up to 24 hours; the job reports New, InProgress, CompleteSuccess or CompleteWithFailure. To return a site to the organization default for new libraries, run Set-SPOSite -Identity $site -InheritVersionPolicyFromTenant.

For one library:

Set-SPOListVersionPolicy -Site $site -List "Documents" -EnableAutoExpirationVersionTrim $true
Get-SPOListVersionPolicy -Site $site -List "Documents"

Setting a limit still doesn't delete versions that already exceed it. That is the next step.

Step 5: Queue a trim job

Pick the trim mode that matches the limit you just set and the scope you analyzed.

$site = "https://contoso.sharepoint.com/sites/projects"
 
# Automatic algorithm across the site
New-SPOSiteFileVersionBatchDeleteJob -Identity $site -Automatic
 
# Or delete versions older than 180 days in one library
New-SPOListFileVersionBatchDeleteJob -Site $site -List "Documents" -DeleteBeforeDays 180
 
# Or keep at most 100 major versions per file, with minor versions kept for the latest 10
New-SPOSiteFileVersionBatchDeleteJob -Identity $site -MajorVersionLimit 100 -MajorWithMinorVersionsLimit 10
 
# Track progress
Get-SPOSiteFileVersionBatchDeleteJobProgress -Identity $site
Get-SPOListFileVersionBatchDeleteJobProgress -Site $site -List "Documents"

To trim a library using the limits it already has, run New-SPOListFileVersionBatchDeleteJob -Site $site -List "Documents" -TrimUseListPolicy. For a OneDrive account, use its URL, such as https://contoso-my.sharepoint.com/personal/megan_contoso_com, as the site.

Know the limits of the expiration mode before you use it: it never deletes versions created in the last 30 days, so the value can't be under 30, and it always deletes every version created before January 1, 2023. If you need to keep pre-2023 versions, use automatic or count mode instead.

Trim jobs run in the background, are affected by service load and off-peak processing, and can take days. To stop one, run Remove-SPOSiteFileVersionBatchDeleteJob -Identity $site or Remove-SPOListFileVersionBatchDeleteJob -Site $site -List "Documents". Stopping a job doesn't bring back versions already deleted.

Tenant-wide trimming (preview)

Tenants with SharePoint Advanced Management or Copilot licenses can apply the tenant policy to every site in one job. It is in private preview, allows one job per tenant at a time, and skips read-only, locked and archived sites and sites whose version policy breaks inheritance.

New-SPOTenantApplyFileVersionPolicyJob -CollectVersionData
Get-SPOTenantApplyFileVersionPolicyJobProgress
Get-SPOTenantApplyFileVersionPolicyJobImpact
 
# After reviewing the impact
New-SPOTenantApplyFileVersionPolicyJob -TrimVersions -SetVersionPolicy

Verify the result

  • Check the trim job progress cmdlet until it reports completion.
  • Generate a new version usage report for the site and compare its total Size with the first one.
  • Open Active sites in the SharePoint admin center a day or two later; the storage figure doesn't include the last 24 to 48 hours of changes.
  • Open the version history of a few heavily edited files and confirm the expected versions remain.
  • In the Microsoft Purview portal, search the audit log for the version events: changes to organization, site and library limits, queued report and trim jobs, and versions deleted when expired or bulk deleted.

Troubleshooting

The report job returns failed. Read the error_message field. Check that the report URL points into a document library and that no file with that name already exists there.

Progress returns no_report_found. No active job is writing to that file. Confirm the site, list and report URL match the values used when you queued the job.

The site update job ends in CompleteWithFailure. Some libraries didn't take the new limit. Check them with Get-SPOListVersionPolicy and set the limit per library, or sync them to the site with Set-SPOListVersionPolicy -Sync.

Storage barely changes after the trim. Look for retention policies and eDiscovery holds: limits are ignored for that content, and trim jobs only stamp expiration dates on it. Also check whether the site is read-only or locked, which suspends trimming, and whether the Preservation Hold library holds most of the version data.

Versions keep growing on a library after you lowered its count. Excess versions are removed gradually, up to 20 for each new version of a file. Queue a trim job to remove them at once.

A new library didn't get the organization limit. Organization changes can take up to 24 hours to reach new libraries, and a site-level setting overrides the organization one.

Checklist

  • Recovery objective agreed and backup coverage confirmed before any trimming.
  • Organization default set, ideally to automatic, for new libraries and OneDrive accounts.
  • File type overrides set for large media files if needed.
  • Version usage report generated for each large site and a what-if analysis reviewed.
  • Site owners informed about files that will lose most of their versions.
  • Site or library limits applied to existing content and the background job completed.
  • Trim jobs queued with the matching mode and tracked to completion.
  • Storage, version history and audit events checked after the trim.

References

Questions people ask

What is the default SharePoint version history limit?

Microsoft documents the default organization setting as manual limits with a 500 major version count and no expiration. Admins can change it to automatic limits or to a different count and expiration in the SharePoint admin center under Settings, Version history limits.

Does changing the organization version limit delete existing versions?

No. Organization-level changes apply only to new document libraries and new OneDrive accounts. Existing libraries keep their settings and their existing versions until you update them at site or library level and queue a trim job.

Can versions deleted by a trim job be restored?

No. Versions deleted by trim jobs, or because they exceed a library's limits, bypass the recycle bin and are permanently deleted. Only versions a user deletes manually from a file's version history go to the recycle bin. Microsoft recommends running a what-if analysis before trimming.

How does the automatic version history setting decide what to keep?

It keeps all versions, within a 500 count limit, for the first 30 days, then hourly versions from 30 to 60 days, daily versions from 60 to 180 days, and weekly versions beyond 180 days until the 500 count limit is reached. Intermediate versions are trimmed as each milestone is passed.

SharePoint OnlineOneDriveSharePoint Online Management ShellVersion history
  1. SharePoint and OneDrive standalone plan retirement: licensing paths to 2029

    Microsoft is retiring SharePoint Online Plan 1 and 2 and OneDrive for Business Plan 1 and 2. Find affected users, size storage and move them to a suite or storage add-on.

    Microsoft 36514 min read
  2. SharePoint Migration Tool: move file shares to SharePoint and OneDrive

    Plan, scan and migrate on-premises file shares to SharePoint, OneDrive and Teams with the SharePoint Migration Tool or Migration Manager, then verify the result with the migration reports.

    Microsoft 36517 min read
  3. SharePoint Online external sharing settings at tenant and site level

    Configure SharePoint and OneDrive guest sharing end to end: Entra B2B invite settings, tenant and site sharing levels, domain limits, Anyone link expiry and guest access expiration.

    Microsoft 36513 min read