Diagnostics Persistence automatically captures and stores Inspect data across
device reboots. This can be used to preserve anything that can be written to
Inspect.

## Overview

- **Automatic collection in development** : On `eng` and `userdebug` builds,
  all Inspect data across the system is automatically persisted across
  reboots. No configuration required.

- **Production (`user`) builds require privacy configuration** : On production
  devices, persisted Inspect data must be explicitly allowlisted in a
  product's `previous_boot` pipeline (for example, in go/previous-boot-pipeline)
  and undergo privacy review.

- **Available in Feedback \& Crash Reports** : Persisted Inspect data is
  automatically ingested by Feedback and included in snapshot archives
  (as `inspect.previous_boot.json`) when generating feedback or crash reports.

## Field collection on user builds

On production (`user`) builds, diagnostic data exfiltration is restricted for
user privacy. To persist specific Inspect properties or trees on production
devices, you must add your selectors to the product's `previous_boot` pipeline
and complete a privacy review.

The privacy requirements for Persistence are functionally identical to
go/tq-feedback-privacy.

### 1. Identify Inspect selectors

Determine the exact Inspect selectors for the properties or nodes you need.
You can inspect your component on a running device or emulator using
`ffx inspect`.

### 2. Add selectors to the previous_boot pipeline

Create or update the selector configuration for your component in the product
repository's pipeline directory:

1. Create a component directory under the product's `previous_boot` pipeline:

       //vendor/*/privacy/pipelines/previous_boot/<component_name>/inspect/

2. Add a `.cfg` file (e.g. `<component_name>.cfg`) containing the exact
   selectors to persist:

       core/my_component:root/my_node:error_count
       core/my_component:root/my_node:last_failure_reason

3. Update the corresponding `BUILD.bazel` or pipeline list to include your
   new configuration.

### 3. Submit for privacy review

Refer to go/tq-feedback-privacy.

## Accessing persisted data

### Feedback reports and snapshots

When a feedback report or crash snapshot is taken after a reboot, Feedback
automatically retrieves the previous boot's Inspect data from Persistence.
The resulting snapshot contains:

- `inspect.previous_boot.json`: The complete or filtered Inspect JSON tree from the prior boot.

## Technical architecture and behavior

Under the hood, Diagnostics Persistence operates as a scheduled and
event-driven pipeline snapshotting service:

    ┌───────────────────────────┐
    │ Archivist                 │
    │ ArchiveAccessor           │
    │ .previous_boot pipeline   │
    └─────────────┬─────────────┘
                  │ Snapshot query
                  ▼
    ┌───────────────────────────┐   writes active snapshot
    │ Diagnostics Persistence   ├───► /cache/active/active.json
    │                           │     /cache/active/metadata.json
    │ • Periodic (every 300s)   │
    │ • Low battery trigger     │   on reboot: rotate
    │ • Wait for update check   ├───► /cache/previous_boot/active.json
    └─────────────┬─────────────┘     /cache/previous_boot/metadata.json
                  │ Serves via FIDL
                  ▼
    ┌───────────────────────────┐
    │ PreviousBootDataProvider  │
    │ (e.g. Feedback component) │
    └───────────────────────────┘

### 1. Archivist previous_boot pipeline

Persistence connects to `fuchsia.diagnostics.ArchiveAccessor.previous_boot`.
Archivist dynamically applies the allowlist selectors configured for the
pipeline, or bypasses filtering when `DISABLE_FILTERING.txt` is present (such
as in `eng` and `userdebug` builds).

### 2. Snapshot triggers

Persistence records active system snapshots using two triggers:

- **Periodic Interval** : Runs every $N$ seconds (configured by
  `fuchsia.diagnostics.persist.PersistencePeriodSeconds`, default 300 seconds).

- **Low-Battery Trigger** : Connects to
  `fuchsia.power.battery.BatteryManager` to monitor battery status. If
  battery drops to or below
  `fuchsia.diagnostics.persist.LowBatteryThresholdPercent` (default 10%), an
  immediate snapshot is captured to preserve state prior to impending
  shutdown.

### 3. Active-to-previous boot rotation

- Active snapshots and metadata are saved to `/cache/active/active.json` and
  `/cache/active/metadata.json`.

- On startup, Persistence atomically cleans `/cache/previous_boot` and moves
  `/cache/active` to `/cache/previous_boot`.

- Persisted data is retained strictly for the single previous boot cycle.

### 4. Software update check gating

To protect against persistent crash loops across updates, Persistence
registers with `fuchsia.update.Listener` and withholds serving previous boot
data until the first post-boot software update check completes. On `eng` and
`userdebug` builds, this check can be skipped (`skip_update_check: true`).

## Assembly configuration

Persistence parameters can be customized in product assembly configuration
under the `diagnostics.persistence` section:

- `persistence_period_seconds` (integer, default: `300`):
  Duration in seconds between periodic snapshots on
  `ArchiveAccessor.previous_boot`.

- `low_battery_threshold_percent` (integer, default: `10`):
  Battery percentage threshold that triggers an immediate active snapshot.

- `skip_update_check` (boolean, default: `false` on user, `true` on
  userdebug/eng):
  If `true`, does not wait for the post-boot update check before publishing
  previous boot data. Always `false` on user builds.

## FAQ

### Does Persistence work with Lazy Nodes?

Yes. Because Persistence requests a snapshot from Archivist via
`ArchiveAccessor`, Archivist actively evaluates all Lazy Nodes that match the
pipeline's active selectors at the time of each snapshot.

### Where did .persist configuration files go?

Legacy `.persist` files and per-tag fetch scheduling have been replaced by the
Archivist `previous_boot` pipeline. Components no longer publish separate
`.persist` files or re-export persisted data in the live Inspect hierarchy
under `core/diagnostics/persistence:root/persist`. All previous boot Inspect
is unified into a single snapshot file served directly to Feedback.
[](https://issues.fuchsia.dev/issues/new?component=1439230&template=1881640&description=Issue+on:+https://fuchsia.dev/docs/development/diagnostics/analytics/persistence.md "Report a bug or suggest improvements on this page") [](https://cs.opensource.google/fuchsia/fuchsia/+/main:docs/development/diagnostics/analytics/persistence.md "View the source code of this page") [](https://ci.android.com/edit?repo=fuchsia/fuchsia/main&file=docs/development/diagnostics/analytics/persistence.md&cloneRepo=fuchsia/fuchsia:refs/heads/main&fullPath=fuchsia/docs/development/diagnostics/analytics/persistence.md "Edit the source code of this page")