HotupdaterHot Updater
Operate

Storage Cleanup

Safely reclaim unreferenced bundle artifacts and shared assets with the storage prune command.

How pruning works

hot-updater storage prune is reference-aware garbage collection. It reads all bundle records and their manifests, lists the configured storage prefix, and selects only objects that are no longer referenced.

It can remove:

  • Orphaned bundle objects under bundles/<artifact-id>/..., where the artifact ID is a UUIDv7.
  • Patch objects that are no longer referenced, including orphaned patches under a target Bundle that is still live.
  • Unreferenced content-addressed assets under assets/sha256/....

Live bundle objects, referenced patches and assets, recently modified objects, objects without a modification timestamp, and unknown files are protected. Root-level <artifact-id>/... paths are not recognized and remain protected.

Pruning does not delete live bundle records. Delete records you no longer need before pruning their unreferenced objects.

Remove bundles

Start by listing the bundles you intend to retire:

npx hot-updater bundle list --channel production --platform ios --limit 100 --json

Disable each selected bundle, then hard-delete it. Hard deletion is separate from operational rollback.

npx hot-updater bundle disable <id> --yes
npx hot-updater bundle delete <id> --yes

Multiple bundle IDs can share one immutable artifact, such as a promoted bundle and its source. Deleting the last bundle that uses an artifact deletes the artifact's record too, with every patch to or from it, so a device running that bundle can no longer use it as a Hermes patch base. Unchanged files can still be reused from the device; changed files download in full. bundle delete reports the artifact deletion, and its --json output names the artifact in deletedArtifactId.

hot-updater doctor reports artifact records no bundle uses as UNREFERENCED_ARTIFACTS, and doctor --fix deletes them so the prune below can reclaim their files.

A delete removes database records only. Bundle files, patch objects, and shared assets remain until a reference-aware prune confirms that no remaining record uses them.

Preview eligible objects

Run an explicit dry run first:

npx hot-updater storage prune --dry-run

The preview shows each eligible object, its modification time, size, type, and the total reclaimable size. The command fails closed if it cannot load all bundle references or required manifests.

The default --protect-newer-than 24h window compares the current time with each object's storage lastModified timestamp. It does not measure time since the bundle record was deleted. Increase the window when deployments may remain in flight for longer:

npx hot-updater storage prune --dry-run --protect-newer-than 7d

Durations accept m, h, d, or w, such as 30m, 24h, 7d, or 2w.

Delete eligible objects

Pause every deploy and patch process that writes to the same storage prefix, then run:

npx hot-updater storage prune --protect-newer-than 24h --yes

Before deletion, Hot Updater reloads bundle and manifest references and removes objects from the candidate set if they became live.

bundle promote does not need to be paused for Storage safety. It creates a new bundle ID that reuses an existing artifact and does not upload or copy Storage objects.

The configured database must own every object under the configured storage prefix; without basePath, that is the whole bucket. If databases or environments share a bucket, assign each one a separate storage basePath before pruning.

Storage pruning currently requires the listObjects and deleteObjects management capabilities provided by s3Storage, including AWS S3 and S3-compatible services such as Cloudflare R2. Other Storage adapters continue to support deploy and runtime delivery but cannot use storage prune until they implement those management operations.

On this page