Skip to main content
Contents

Docs › Platform admin

Uploaded files

Photos and images people upload are stored as files, not in the database. That covers staff photos, profile photos, product photos, site logos and favicons (branding), and the photos attached to scan reports. They all live in the upload folder set by UPLOAD_DIR. If you run more than one copy of the app, every copy must use the same shared folder.

Cleaning up unused files

Some files stop being used without being deleted. For example, a Demo site reset removes its products but leaves their photo files, and an upload or delete that fails part-way can leave a file behind. A background job finds files that nothing in the app points at any more and removes them.

It is set with UPLOAD_GC_MODE in the app's environment:

SettingWhat it does
dry-run (the default)Only writes to the server log which files it would delete, with a count and their total size. Nothing is deleted.
deleteDeletes them.
offDoesn't run.

It runs about 10 minutes after the app starts and then every 24 hours (UPLOAD_GC_INTERVAL_HOURS), only on the production server. With several copies of the app, only one of them runs it each time.

Each run that deletes files adds one entry to the Audit Log, "Deleted unused uploaded files", with how many files went and how much space they used.

What it never touches

  • Recent files. Only files older than 24 hours (UPLOAD_GC_MIN_AGE_HOURS) are considered, so a photo that is still being uploaded is never removed.
  • Anything it doesn't recognise. It only looks in the app's own folders (people, users, products, branding, scan-reports), and only at file names the app itself creates. Other files, folders and links are listed in the log and left alone.
  • Anything outside the upload folder. It never follows a link out of it.

It also stops without deleting anything if the database can't be read, if the database refers to no files at all, if none of the files it found are ones the database uses, or if more than half of the files look unused. Each of those usually means UPLOAD_DIR or the database settings point at a different installation, so check them before anything else. Folders left empty are removed.

Running it by hand

From a copy of the app's code, with the same database settings and UPLOAD_DIR as the server:

npm exec -- tsx scripts/upload-gc.ts                  # dry run: list what would go
npm exec -- tsx scripts/upload-gc.ts --delete         # delete it
npm exec -- tsx scripts/upload-gc.ts --min-age-hours 72

If the scheduled cleanup is running at that moment, it says so and stops without doing anything. --force skips only the "more than half look unused" check, for when you know a lot of files really are unused. The other checks always apply.

Related: Platform admin, Branding.