Build a document-retention policy enforcer
Delete Northwind files past their retention date — keep finance, drop drafts.
Published Aug 29, 2025
Northwind has a retention policy on paper — keep finance records for years, clear out drafts after a few months — but no one enforces it. So the draft folders fill up with stale files, and the policy stays a document nobody acts on. The rules are simple enough; they just need a script to apply them.
This automation reads a retention table where each row is a folder and a number of days to keep files. It walks each folder and trashes anything that has not been touched within its window. Point a long window at finance folders, a short one at drafts, and the policy enforces itself.
What you’ll need
- A
RetentionGoogle Sheet with a header row and two columns:folderId(a Drive folder ID) andkeepDays(a whole number of days). - The retention sheet’s own file ID.
- Edit access to every folder listed, so the script can trash files in them.
The script
// The sheet that maps each folder to its retention window in days.
const RETENTION_SHEET_ID = '1abcRetentionId';
// Milliseconds in a day — used to turn keepDays into a cutoff time.
const MS_PER_DAY = 86400000;
/**
* Reads the retention table and trashes files in each folder that
* have not been updated within that folder's retention window.
*/
function enforceRetention() {
// Read the table and drop the header row.
const [_header, ...rows] = SpreadsheetApp.openById(RETENTION_SHEET_ID)
.getSheets()[0]
.getDataRange()
.getValues();
// Bail out early if there are no rules to apply.
if (!rows.length) {
Logger.log('No retention rules — nothing to enforce.');
return;
}
let trashed = 0;
for (const [folderId, keepDays] of rows) {
// Skip blank or malformed rows.
if (!folderId || !keepDays) continue;
// Anything not updated since this cutoff is past its retention window.
const cutoff = Date.now() - parseInt(keepDays, 10) * MS_PER_DAY;
const files = DriveApp.getFolderById(folderId).getFiles();
while (files.hasNext()) {
const f = files.next();
if (f.getLastUpdated().getTime() < cutoff) {
f.setTrashed(true);
trashed++;
}
}
}
Logger.log(`Trashed ${trashed} file(s) past retention.`);
}
How it works
enforceRetentionopens the retention sheet, reads every row, and discards the header.- If the table holds no rules, it logs a message and stops.
- For each row it skips any with a missing
folderIdorkeepDays, so a blank line in the sheet does not break the run. - It calculates a
cutofftimestamp: the current time minus the folder’skeepDayswindow. Any file last updated before that moment is past its retention period. - It opens the folder and iterates over its files, comparing each file’s
getLastUpdated()time against the cutoff. - Files older than the cutoff are sent to the trash with
setTrashed(true). - After every folder is processed it logs how many files were trashed.
Example run
The Retention sheet holds two rules:
| folderId | keepDays |
|---|---|
| 1xFinanceFolder | 2555 |
| 1xDraftsFolder | 90 |
On a run dated 25 May 2026, the cutoffs work out as roughly 7 years ago for finance and 90 days ago for drafts:
| File | Folder | Last updated | Result |
|---|---|---|---|
| Invoice 2019-04 | Finance | 2019-04-10 | kept (within 7 years) |
| Old tax record 2015 | Finance | 2015-02-01 | trashed |
| Logo draft v3 | Drafts | 2026-05-10 | kept (within 90 days) |
| Pitch draft (Jan) | Drafts | 2026-01-15 | trashed |
The log reads Trashed 2 file(s) past retention.
Trigger it
Retention is an ongoing job, so run it on a schedule:
- In the Apps Script editor open Triggers (the clock icon).
- Click Add Trigger.
- Choose
enforceRetention, a Time-driven source, and a Week timer — weekly is frequent enough for a retention policy. - Save and approve the authorisation prompt.
To change the policy, just edit the Retention sheet — no code change needed.
Watch out for
- Trashed files stay recoverable for 30 days. For permanent, unrecoverable
deletion use the Drive API’s
files.deleteendpoint — but be certain first. - The script only looks at files directly in each folder, not in sub-folders. Add a recursive walk if your structure is nested.
getLastUpdated()reflects the last edit by anyone, including a stray rename or comment. A file someone glanced at last week will not be trashed even if its content is years old.- Test with a long window on a sample folder before pointing it at real data.
A wrong
keepDaysvalue can trash a whole folder in one run. - Large folders may hit the 6-minute execution limit. Split big folders across multiple rules, or process them with a continuation trigger.
Related
Detect and report broken file shortcuts
Find Drive shortcuts in Northwind folders pointing at deleted or inaccessible files.
Updated Dec 3, 2025
Build a Drive cleanup recommendation report
Suggest what Northwind can delete or archive — large, stale, duplicate, or untouched files.
Updated Nov 21, 2025
Generate a folder-level changelog
Track additions and deletions in a Northwind folder over time — a written history.
Updated Nov 5, 2025
Track contract expiry from Drive files
Read expiry dates out of Northwind contract Docs and warn before renewals.
Updated Oct 28, 2025
Build a Drive quota early-warning system
Alert Northwind before storage runs out — email when usage crosses 80%.
Updated Oct 20, 2025