Garbage Collection (GC) is the process for removing "unnecessary" blobs from a
device. It is usually performed to free up disk space so that new ephemeral
packages can be resolved or to OTA (which internally makes use of package
resolution).

## How to trigger

GC is implemented by pkg-cache, which exposes the functionality via [fuchsia.pkg.garbagecollector/Manager.GC](https://cs.opensource.google/fuchsia/fuchsia/+/main:sdk/fidl/fuchsia.space/space.fidl;l=18;drc=4eae0501e94a15718fea7e2410b55ef0e0fef979).

It can be triggered manually by running `fx shell pkgctl gc`.

It is automatically triggered (if necessary) at various points during OTA by the
[system-updater](https://cs.opensource.google/fuchsia/fuchsia/+/main:src/sys/pkg/bin/system-updater/src/update.rs;l=1254;drc=f183b2bad311eb09c2be4d72411ddfd8e8db6e63).

It is automatically triggered (if necessary) by the [system-update-checker](https://cs.opensource.google/fuchsia/fuchsia/+/main:src/sys/pkg/bin/system-update-checker/src/check.rs;l=178;drc=f183b2bad311eb09c2be4d72411ddfd8e8db6e63),
which is the update checker used by engineering builds.

pkg-cache can also trigger GC automatically after an OTA, once the new system
commits during the current boot. This behavior is disabled by default. You can
enable it in [product configuration](https://cs.opensource.google/fuchsia/fuchsia/+/main:/src/lib/assembly/config_schema/src/platform_settings/swd_config.rs) by setting
`platform.software_delivery.post_commit_gc_earliest_boot_seconds` to the
earliest time (in seconds) on the boot timeline at which post-commit GC runs.
pkg-cache skips post-commit GC if GC already completed during that boot, and
doesn't retry it on later boots if the device reboots before it runs.

## The algorithm

The [current algorithm](https://cs.opensource.google/fuchsia/fuchsia/+/main:src/sys/pkg/bin/pkg-cache/src/gc_service.rs;l=52;drc=c33e19363ac233f6be9d8cb9df460fc0e30551ad) is based on the design
proposed by the [Open Package Tracking RFC](https://fuchsia.dev/docs/contribute/governance/rfcs/0217_open_package_tracking).

### Definitions

- **[Base packages](https://cs.opensource.google/fuchsia/fuchsia/+/main:src/sys/pkg/bin/pkg-cache/src/base_packages.rs;l=36;drc=d7e51f5a7d6b09dcc24b684aa19ccda7eb6c0757)**
  - The "base" or "system_image" package (identified by hash in the boot arguments) and the packages listed (by hash) in its `data/static_packages` file.
  - Generally intended to be the minimal set of packages required to run a particular configuration.
- **[Cache packages](https://cs.opensource.google/fuchsia/fuchsia/+/main:src/sys/pkg/lib/system-image/src/cache_packages.rs;l=16;drc=156eb8041a38d097e146c99f54fcb06aaa3c7fe6)**
  - The packages listed (by hash) in the "base" package's `data/cache_packages.json` file.
  - Conceptually packages that we would like to use without networking but still want the option to ephemerally update.
- **[Open packages](https://cs.opensource.google/fuchsia/fuchsia/+/main:src/sys/pkg/lib/package-directory/src/root_dir_cache.rs;l=45;drc=a507f17eb78a603033c068d1f7f0d4d05c28cf20)**
  - Packages whose package directories are [currently being served](https://cs.opensource.google/fuchsia/fuchsia/+/main:src/sys/pkg/bin/pkg-cache/src/main.rs;l=187;drc=3adb26a7b1c4589755132a1fe3b918b6128bac6f) by pkg-cache
- **[Writing index](https://cs.opensource.google/fuchsia/fuchsia/+/main:src/sys/pkg/bin/pkg-cache/src/index/writing.rs;l=21;drc=fe32c41fc7cec966080646c47cb1f4ff1874452f)**
  - Packages whose blobs are currently being written as part of a resolve
- **[Retained index](https://cs.opensource.google/fuchsia/fuchsia/+/main:src/sys/pkg/bin/pkg-cache/src/index/retained.rs;l=14;drc=e3239bddfc70bc7076a1c54f97f2408a95a4b207)**
  - Packages that were/will be downloaded during OTA and are used during the OTA process or are necessary for the next system version.
  - [Manipulated](https://cs.opensource.google/fuchsia/fuchsia/+/main:sdk/fidl/fuchsia.pkg/cache.fidl;l=292;drc=905c18c5ba0899a26963cb9dc5fcf1343068c0cc) by the [system-updater](https://cs.opensource.google/fuchsia/fuchsia/+/main:src/sys/pkg/bin/system-updater/src/update.rs;l=1402;drc=f183b2bad311eb09c2be4d72411ddfd8e8db6e63) during the OTA process to meet the OTA storage requirements.
- **Package blobs**
  - All the blobs required by a package.
  - The meta.far and content blobs, plus the package blobs of all subpackages, recursively.
  - As a result of this definition, protecting a package from GC protects all of its subpackages. The subpackages, as packages themselves, may or may not be protected independently of protection provided by a superpackage.

### Implementation

1. Fail if the current boot partition has not been marked healthy, to avoid deleting blobs needed by the previous system in case of fallback
2. Determine the set of all resident blobs, `Br`
3. Lock the Writing and Retained indices
4. Determine the set of all protected blobs, `Bp`, which is the package blobs of all of the following packages:
   - Base packages
   - Cache packages
   - Open packages
   - Writing index packages
   - Retained index packages
5. Delete the blobs of the set difference `Br - Bp`
6. Unlock the Writing and Retained indices

[](https://issues.fuchsia.dev/issues/new?component=1439230&template=1881640&description=Issue+on:+https://fuchsia.dev/docs/concepts/packages/garbage_collection.md "Report a bug or suggest improvements on this page") [](https://cs.opensource.google/fuchsia/fuchsia/+/main:docs/concepts/packages/garbage_collection.md "View the source code of this page") [](https://ci.android.com/edit?repo=fuchsia/fuchsia/main&file=docs/concepts/packages/garbage_collection.md&cloneRepo=fuchsia/fuchsia:refs/heads/main&fullPath=fuchsia/docs/concepts/packages/garbage_collection.md "Edit the source code of this page")