SharePoint versioning is one of those features that sounds entirely reasonable until it quietly devours your storage quota.
We can see this with Microsoft taking back storage by ways of deleting unlicensed OneDrive accounts, and applying a default expiration policy for Teams meeting recordings.
However, many times we are victims of our own doing.
The Problem
The ability to limit version counts helps – in theory. In practice, all it takes is a handful of problem files to blow out a siteโs allocation completely.
The most common offender I’ve seen is PowerPoint.
Why? Because unlike many file types, PowerPoint doesnโt handle incremental versioning. Every save creates a new version at roughly the same size as the original file. Pair that with autosave in desktop apps and a file with embedded videos and large images, and the maths gets ugly fast.
Let’s take a scenario of building a presentation that leverages an existing slide pack. You start of fresh by creating a new blank presentation and copying all the existing slides into the new one (or you duplicate the file and modify, whatever is your approach).
The file was 250MB to start off with due to uncompressed images and maybe some videos or demos; so that’s your starting point.
First, you update the presenter’s name on the title slide. While looking at what date the presentation will be, AutoSave has kicked in and you’re now at 500MB.
You update the date, but now you want to make sure that you display the client name properly (i.e. avoiding abreviations, acronyms, capitalisation, etc.). In the few seconds you considered that, AutoSave kicked in againย and you’re now at 750MB.
After you actually update the client name on the title slide and press save, you’re already sitting at 1GB. And this has happened in less than a minute!
Iโve seen PowerPoint files of a few hundred megabytes balloon to tens of gigabytes purely from version accumulation, especially when multiple people are collaborating on the same file. Any large binary file that doesnโt support delta/incremental saves has the same problem. PowerPoint is just the most common example in the modern world. Why it doesn’t support deltas is beyond me.
The Challenge
Let’s say, you tighten up the version limit settings and call it done. Except that only stops the bleeding going forward – it doesnโt necessarily clean up whatโs already sitting there. Especially if you go with the default of 500 versions, that won’t make much difference on PowerPoint files that for example, only have 50 versions but their size is already in the gigabytes.
How can we bulk delete at scale? Sorry, I mean, bulk clean. Bulk trim. Bulk tidy. Whatever term you want to use.
A while back I was working on a client project where they had SharePoint sites in the terabytes because of this issue, and it was causing problems.ย
The new CIO wanted to simply pay for an archiving solution that utilised cold storage (my read between the lines of this approach: he wanted a quick win to be a hero). However, I argued that thisย was simply kicking the problem down the line, for when the next CIO comes in and asks why the costs of their archival storage continue to increase so much.
So, I had to figure out how we could address the core of their storage issue – and that was to get rid of the versions.
However, the SharePoint approach to version management is simplistic, and you can see why. Office files in SharePoint and OneDrive already tell you about the differences between versions when you look at their activity history, but that requires you to open the app to see that (separate from the version history). So, doing it at scale is a bit of a challenge. And really, this is your problem.
The Solution
Enter… Microsoft Graph!
In my research to find a scalable solution, I found that theย driveItemVersion documentationย page in the Microsoft Graph documentation covers listing versions and getting a specific version, but it doesn’t have anything about deleting one.
I thought I’d give it a try to see if it worked, and to my surprise it did!
That absence of it in the documentation is mildly frustrating, because it works. Itโs consistent with standard Graph API conventions, and given that list and get are both documented, so the omission of delete feels like an oversight rather than a deliberate restriction.
So, what does the structure this undocumented endpoint action look like?
DELETE https://graph.microsoft.com/v1.0/drives/<SharePoint library ID>/items/<SharePoint drive item ID>/versions/<version number>
A few things worth knowing before you run with this:
- Iโve only tested this with an app registration in Entra ID that used application permissions, not delegated.
- The deletion of versions (whether via Graph or web UI) seems to ignore retention policies. If youโre operating in a regulated environment, test carefully before running anything at scale.ย
- Be VERY specific about what you’re deleting, as this doesn’t care about what’s in the version it deletes.
I recently used this method to purge 3TB of file versions across a SharePoint environment. Total time: eight minutes.
Yes, you read that right. Three terabytes of version history deleted in eight minutes. That might not seem like a lot but consider that this was a workflow that was looping through hundreds of versions in performing this action.
The Graph API handles the heavy lifting efficiently once you have the right flow in place.
The general approach I used by doing this in Power Automate:
- Identify libraries and files – get the list of document libraries across the target sites using the SharePoint or Graph connector, then enumerate the files within each library.
- Retrieve versions – for each file, call theย
driveItemVersionlist endpoint to get all versions for that item. - Filter to versions you want to remove – typically anything beyond the N most recent, versions older than a defined date, or all versions for files above a certain size threshold, or that total a certain size.
- Call DELETE for each individual version – iterate through the filtered list and issue a DELETE request per version using an HTTP action in Power Automate with application authentication.
Additionally, I would suggest preserving the first version or two of the files. In my version of this solution, I retrieved versionsย after the first 5.
The SharePoint library ID comes from the drive endpoint for the site. The item ID comes from listing items within that drive. Both are straightforward Graph calls.
Before assuming the issue is widespread across your tenant, itโs worth auditing which libraries contain the largest files.
In my experience the storage blowout tends to be concentrated in a relatively small number of sites – usually ones used by specific teams for client-facing material or large media files. Targeting those first gives you the biggest return for the effort.
Set your version limits going forward, run the purge to clear the historical backlog, and the problem stays manageable.
And make sure you get someone with business authority to validate and sign off on what you’re purging!
Tip: If youโre building workflows against the Graph API and want to stay current on whatโs being added, changed, or deprecated, the Graph changelog is the place to start. The RSS feed is often more current than the changelog page itself, but that’s whole other conversation!
Discover more from Loryan Strant, Microsoft 365 MVP
Subscribe to get the latest posts sent to your email.
