One of the things most people don’t know when creating a Group or a Team with an associated SharePoint Site, or even a new sitecollection, is that out of the box, its document libraries (or similar) have versioning enabled and supporting a maximum of 500 versions. This a cool feature, but can impact your Office365 storage quota and severely decrease its size.

Did you know that every time you edit and save a file on a document library in SharePoint, either via Office Web Apps (Word, Excel, PowerPoint Online) or locally, you’re creating a new version of that file?

For instance, let’s say you’ve initially uploaded a 10mb file and then edited it 10 times. This means that you now have 10 versions of that file using 100mb of space.

SharePoint Versioning

Because your tenant probably has a lot of SharePoint sites with several documents (or items) with versioning enabled, we’ve created a PowerShell script that allows you to change the maximum number of versions.

By doing this, lower versions are deleted from your sites, consequently increasing the storage size available.

PowerShell Script

param (
    [string]$majorVersionsLimit = 100,
    [string]$minorVersionsLimit = 5, 
    [string]$tenantUrl = $(throw "-tenantUrl is required.")

$psCred = Get-Credential

#$psCred = New-Object System.Management.Automation.PSCredential -ArgumentList ($username, $password)
Connect-PnPOnline -url $tenantUrl -Credential $psCred

$tenantSites = Get-PnPTenantSite -IncludeOneDriveSites
$currentSizeUsage = 0
$afterSizeUsage = 0
$exportInfo = @()

function SetVersioningOnItems($ctx, $items)
    $items | ForEach-Object {

            #Get File Versions
            $File = $_.File
            $Versions = $File.Versions

            Write-host -f Yellow "--- Scanning File:"$File.Name
            $VersionsCount = $Versions.Count
            $VersionsToDelete = $VersionsCount - $minorVersionsLimit
            If($VersionsToDelete -gt 0)
                write-host -f Cyan "`t --- Total Number of Versions of the File:" $VersionsCount
                #Delete versions
                For($i=0; $i -lt $VersionsToDelete; $i++)
                    write-host -f Cyan "`t --- Deleting Version:" $Versions[0].VersionLabel
                Write-Host -f Green "`t --- Version History is cleaned for the File:"$File.Name
        catch { }

function SetVersioningOnLists($list, $ctx)
    $items = Get-PnPListItem -List $list.Id -Query "<View Scope='RecursiveAll'><Query><Where><Eq><FieldRef Name='FSObjType'/><Value Type='Integer'>0</Value></Eq></Where></Query></View>"
    SetVersioningOnItems $ctx $items

    if($list.EnableMinorVersions -eq $true){
        Set-PnpList -Identity $list.ID -MinorVersions $minorVersionsLimit -ErrorAction Stop
        Set-PnpList -Identity $list.ID -MajorVersions $majorVersionsLimit -ErrorAction Stop
        Set-PnpList -Identity $list.ID -MajorVersions $majorVersionsLimit -ErrorAction Stop
    Write-Host "-- Versioning on list has been set" -ForegroundColor Green

$tenantSites | ForEach-Object {

    Connect-PnPOnline -Url $_.Url -Credentials $psCred
    $allLists = Get-PnPList
    $siteUrl = $_.Url
    Write-Host "-" $siteUrl "with " $_.StorageUsage "MB" -ForegroundColor Yellow

    $ctx= Get-PnPContext

    $initialSize = $_.StorageUsage
    $currentSizeUsage = $initialSize + $currentSizeUsage

    $exportInfo += New-Object -TypeName PSObject -Property @{            
        SiteCollection = $siteUrl              
        InitialStorageUsage =  $initialSize             
        FinalStorageUsage = 0

    $allLists | where-object { 
    $_.EnableVersioning -eq $true -and ($_.MajorWithMinorVersionsLimit -gt $minorVersionsLimit -or $_.MajorVersionLimit -gt $majorVersionsLimit)
    } | ForEach-Object {
        Write-Host "--" $_.Title -ForegroundColor DarkYellow 
            SetVersioningOnLists $_ $ctx                          
        catch {
            Write-Host "-- It was not possible to set versioning -" $_.Exception.Message -ForegroundColor Red


## Workaround to get latest storage quota ###
Connect-PnPOnline -url $tenantUrl -Credential $psCred
Get-PnPTenantSite -IncludeOneDriveSites | ForEach-Object {
    $currentUrl = $_.Url
    $finalStorageUsage = $_.StorageUsage
    $afterSizeUsage = $_.StorageUsage + $afterSizeUsage

    $exportInfo | where-object { $_.SiteCollection -eq $currentUrl } | ForEach-Object { $_.FinalStorageUsage = $finalStorageUsage }

Write-Host "## Tenant had " $currentSizeUsage "MB" -ForegroundColor DarkCyan
Write-Host "## Tenant now has " $afterSizeUsage "MB"  -ForegroundColor DarkCyan

$exportInfo | export-csv -Path C:\Temp\cleanupResults.csv -NoTypeInformation

This script goes through every sitecollection and every document library to set the number of versions selected.

In the end, the script creates a CSV file to show the initial and final size of every site collection.

Usage mode:

It sets a maximum number of 100 major versions and 5 minor versions
It sets a maximum number of 200 major versions and 5 minor versions
It sets a maximum number of 200 major versions and 10 minor versions


At DevScope, we usually “Eat Y(our) Own Dog Food”, so we tried the script on one of our dev tenants and had the following results, which are promising for the first version of this “cleanup script”. Imagine what could be done on a production environment.

You can find this script on our DevScope Ninjas Github.

Sharing is caring!


ICYMI: PowerShell Week of 27-September-2019 | · September 27, 2019 at 4:07 pm

[…] Clear Office 365 Storage Size with Versioning […]

SharePoint Dev Weekly - Episode 54 - Microsoft 365 Developer Blog · October 1, 2019 at 9:58 am

[…] Clear Office 365 Storage Size with Versioning – Ricardo Calejo (devscope) […]

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: